Skip to content

Commit efecc85

Browse files
authored
All tsserver unittests use session and typing installer (#56337)
1 parent 8e1fb57 commit efecc85

File tree

1,350 files changed

+148383
-39173
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,350 files changed

+148383
-39173
lines changed

src/harness/fourslashImpl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as Utils from "./_namespaces/Utils";
66
import * as vfs from "./_namespaces/vfs";
77
import * as vpath from "./_namespaces/vpath";
88
import {
9-
Logger,
9+
LoggerWithInMemoryLogs,
1010
} from "./tsserverLogger";
1111

1212
import ArrayOrSingle = FourSlashInterface.ArrayOrSingle;
@@ -259,7 +259,7 @@ export class TestState {
259259

260260
private inputFiles = new Map<string, string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
261261

262-
private logger: Logger | undefined;
262+
private logger: LoggerWithInMemoryLogs | undefined;
263263

264264
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[] | undefined) {
265265
let result = "";
@@ -519,7 +519,7 @@ export class TestState {
519519
if (this.logger) {
520520
Harness.Baseline.runBaseline(
521521
`tsserver/fourslashServer/${ts.getBaseFileName(this.originalInputFileName).replace(".ts", ".js")}`,
522-
this.logger.logs!.join("\n"),
522+
this.logger.logs.join("\n"),
523523
);
524524
}
525525
}

src/harness/harnessLanguageService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
import {
1818
createLoggerWithInMemoryLogs,
1919
HarnessLSCouldNotResolveModule,
20-
Logger,
20+
LoggerWithInMemoryLogs,
2121
} from "./tsserverLogger";
2222
import {
2323
createWatchUtils,
@@ -130,7 +130,7 @@ export interface LanguageServiceAdapter {
130130
getLanguageService(): ts.LanguageService;
131131
getClassifier(): ts.Classifier;
132132
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo;
133-
getLogger(): Logger | undefined;
133+
getLogger(): LoggerWithInMemoryLogs | undefined;
134134
}
135135

136136
export abstract class LanguageServiceAdapterHost {
@@ -611,7 +611,7 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter {
611611
private host: SessionClientHost;
612612
private client: ts.server.SessionClient;
613613
private server: FourslashSession;
614-
private logger: Logger;
614+
private logger: LoggerWithInMemoryLogs;
615615
constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
616616
// This is the main host that tests use to direct tests
617617
const clientHost = new SessionClientHost(cancellationToken, options);

src/harness/incrementalUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
431431
const getDefaultLibLocation = compilerHost.getDefaultLibLocation!;
432432
compilerHost.getDefaultLibLocation = () => ts.getNormalizedAbsolutePath(getDefaultLibLocation(), service.host.getCurrentDirectory());
433433
compilerHost.getDefaultLibFileName = options => ts.combinePaths(compilerHost.getDefaultLibLocation!(), ts.getDefaultLibFileName(options));
434+
compilerHost.trace = ts.noop; // We dont want to update host just because of trace
434435
const readFile = compilerHost.readFile;
435436
compilerHost.readFile = fileName => {
436437
const path = project.toPath(fileName);

src/harness/tsserverLogger.ts

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,31 @@ export function nullLogger(): Logger {
5050
}
5151

5252
export function createHasErrorMessageLogger(): Logger {
53-
return {
54-
...nullLogger(),
55-
msg: (s, type) => ts.Debug.fail(`Error: ${s}, type: ${type}`),
56-
};
53+
const logger = nullLogger();
54+
logger.msg = (s, type) => ts.Debug.fail(`Error: ${s}, type: ${type}`);
55+
return logger;
5756
}
58-
function handleLoggerGroup(logger: Logger): Logger {
57+
function handleLoggerGroup(logger: Logger, host: ts.server.ServerHost, logText: (s: string) => void, sanitizeLibs: true | undefined): Logger {
58+
logger.hasLevel = ts.returnTrue;
59+
logger.loggingEnabled = ts.returnTrue;
60+
logger.host = host;
61+
if (host) logText(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
62+
5963
let inGroup = false;
6064
let firstInGroup = false;
6165
logger.startGroup = () => {
6266
inGroup = true;
6367
firstInGroup = true;
6468
};
6569
logger.endGroup = () => inGroup = false;
66-
const originalInfo = logger.info;
67-
logger.info = s => msg(s, ts.server.Msg.Info, s => originalInfo.call(logger, s));
68-
logger.log = s => originalInfo.call(logger, s);
70+
logger.info = s => msg(s, ts.server.Msg.Info, log);
71+
logger.log = log;
6972
return logger;
7073

74+
function log(s: string) {
75+
logText((sanitizeLibs ? sanitizeLibFileText : ts.identity)(sanitizeLog(s)));
76+
}
77+
7178
function msg(s: string, type = ts.server.Msg.Err, write: (s: string) => void) {
7279
s = `[${nowString(logger)}] ${s}`;
7380
if (!inGroup || firstInGroup) s = padStringRight(type + " seq", " ") + s;
@@ -86,16 +93,19 @@ export function nowString(logger: Logger) {
8693
return `hh:mm:ss:mss`;
8794
}
8895

89-
export function createLoggerWritingToConsole(host: ts.server.ServerHost) {
90-
return handleLoggerGroup({
91-
...nullLogger(),
92-
hasLevel: ts.returnTrue,
93-
loggingEnabled: ts.returnTrue,
94-
perftrc: s => console.log(s),
95-
info: s => console.log(s),
96-
msg: (s, type) => console.log(`${type}:: ${s}`),
96+
export function createLoggerWritingToConsole(host: ts.server.ServerHost, sanitizeLibs?: true) {
97+
const logger = createHasErrorMessageLogger();
98+
logger.logs = [];
99+
logger.logs.push = (...args) => {
100+
args.forEach(s => console.log(s));
101+
return 0;
102+
};
103+
return handleLoggerGroup(
104+
logger,
97105
host,
98-
});
106+
s => console.log(s),
107+
sanitizeLibs,
108+
) as LoggerWithInMemoryLogs;
99109
}
100110

101111
export function sanitizeLog(s: string): string {
@@ -117,6 +127,7 @@ export function sanitizeLog(s: string): string {
117127
s = s.replace(/"exportMapKey":\s*"\d+ \d+ /g, match => match.replace(/ \d+ /, ` * `));
118128
s = s.replace(/getIndentationAtPosition: getCurrentSourceFile: \d+(?:\.\d+)?/, `getIndentationAtPosition: getCurrentSourceFile: *`);
119129
s = s.replace(/getIndentationAtPosition: computeIndentation\s*: \d+(?:\.\d+)?/, `getIndentationAtPosition: computeIndentation: *`);
130+
s = replaceAll(s, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
120131
s = sanitizeHarnessLSException(s);
121132
return s;
122133
}
@@ -135,16 +146,12 @@ export function sanitizeLibFileText(s: string): string {
135146
return s;
136147
}
137148

138-
export function createLoggerWithInMemoryLogs(host: ts.server.ServerHost, sanitizeLibs?: true): Logger {
149+
export interface LoggerWithInMemoryLogs extends Logger {
150+
logs: string[];
151+
}
152+
153+
export function createLoggerWithInMemoryLogs(host: ts.server.ServerHost, sanitizeLibs?: true): LoggerWithInMemoryLogs {
139154
const logger = createHasErrorMessageLogger();
140-
const logs: string[] = [];
141-
if (host) logs.push(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
142-
return handleLoggerGroup({
143-
...logger,
144-
logs,
145-
hasLevel: ts.returnTrue,
146-
loggingEnabled: ts.returnTrue,
147-
info: s => logs.push((sanitizeLibs ? sanitizeLibFileText : ts.identity)(sanitizeLog(s))),
148-
host,
149-
});
155+
logger.logs = [];
156+
return handleLoggerGroup(logger, host, s => logger.logs!.push(s), sanitizeLibs) as LoggerWithInMemoryLogs;
150157
}

src/server/session.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,9 +1131,10 @@ export class Session<TMessage = string> implements EventSender {
11311131
}
11321132

11331133
private projectsUpdatedInBackgroundEvent(openFiles: string[]): void {
1134-
this.projectService.logger.info(`got projects updated in background, updating diagnostics for ${openFiles}`);
1134+
this.projectService.logger.info(`got projects updated in background ${openFiles}`);
11351135
if (openFiles.length) {
11361136
if (!this.suppressDiagnosticEvents && !this.noGetErrOnBackgroundUpdate) {
1137+
this.projectService.logger.info(`Queueing diagnostics update for ${openFiles}`);
11371138
// For now only queue error checking for open files. We can change this to include non open files as well
11381139
this.errorCheck.startNew(next => this.updateErrorCheck(next, openFiles, 100, /*requireOpen*/ true));
11391140
}
@@ -1193,7 +1194,7 @@ export class Session<TMessage = string> implements EventSender {
11931194
public send(msg: protocol.Message) {
11941195
if (msg.type === "event" && !this.canUseEvents) {
11951196
if (this.logger.hasLevel(LogLevel.verbose)) {
1196-
this.logger.info(`Session does not support events: ignored event: ${JSON.stringify(msg)}`);
1197+
this.logger.info(`Session does not support events: ignored event: ${stringifyIndented(msg)}`);
11971198
}
11981199
return;
11991200
}

src/testRunner/unittests/helpers/tscWatch.ts

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {
2020
import {
2121
changeToHostTrackingWrittenFiles,
2222
File,
23+
SerializeOutputOrder,
24+
StateLogger,
2325
TestServerHost,
2426
TestServerHostTrackingWrittenFiles,
2527
} from "./virtualFileSystemWithWatch";
@@ -63,13 +65,12 @@ export interface TscWatchCompile extends TscWatchCompileBase {
6365
export const noopChange: TscWatchCompileChange = {
6466
caption: "No change",
6567
edit: ts.noop,
66-
timeouts: sys => sys.logTimeoutQueueLength(),
68+
timeouts: ts.noop,
6769
};
6870

69-
export type SystemSnap = ReturnType<TestServerHost["snap"]>;
7071
function tscWatchCompile(input: TscWatchCompile) {
7172
it("tsc-watch:: Generates files matching the baseline", () => {
72-
const { sys, baseline, oldSnap } = createBaseline(input.sys());
73+
const { sys, baseline } = createBaseline(input.sys());
7374
const {
7475
scenario,
7576
subScenario,
@@ -92,7 +93,6 @@ function tscWatchCompile(input: TscWatchCompile) {
9293
commandLineArgs,
9394
sys,
9495
baseline,
95-
oldSnap,
9696
getPrograms,
9797
baselineSourceMap,
9898
baselineDependencies,
@@ -102,44 +102,21 @@ function tscWatchCompile(input: TscWatchCompile) {
102102
});
103103
}
104104

105-
export interface TestServerHostWithTimeoutLogging {
106-
logTimeoutQueueLength(): void;
107-
}
108-
109-
export type TscWatchSystem = TestServerHostTrackingWrittenFiles & TestServerHostWithTimeoutLogging;
105+
export type TscWatchSystem = TestServerHostTrackingWrittenFiles;
110106

111-
function changeToTestServerHostWithTimeoutLogging(inputHost: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
112-
const host = inputHost as TscWatchSystem;
113-
const originalRunQueuedTimeoutCallbacks = host.runQueuedTimeoutCallbacks;
114-
const originalRunQueuedImmediateCallbacks = host.runQueuedImmediateCallbacks;
115-
host.runQueuedTimeoutCallbacks = runQueuedTimeoutCallbacks;
116-
host.runQueuedImmediateCallbacks = runQueuedImmediateCallbacks;
117-
host.logTimeoutQueueLength = logTimeoutQueueLength;
107+
function changeToTestServerHostWithTimeoutLogging(host: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
108+
const logger: StateLogger = {
109+
log: s => baseline.push(s),
110+
logs: baseline,
111+
};
112+
host.timeoutCallbacks.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
113+
host.immediateCallbacks.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
118114
return host;
119-
120-
function logTimeoutQueueLength() {
121-
baseline.push(host.timeoutCallbacks.log());
122-
baseline.push(host.immediateCallbacks.log());
123-
}
124-
125-
function runQueuedTimeoutCallbacks(timeoutId?: number) {
126-
baseline.push(`Before running ${host.timeoutCallbacks.log()}`);
127-
if (timeoutId !== undefined) baseline.push(`Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${host.timeoutCallbacks.map[timeoutId].args[0]}`);
128-
originalRunQueuedTimeoutCallbacks.call(host, timeoutId);
129-
baseline.push(`After running ${host.timeoutCallbacks.log()}`);
130-
}
131-
132-
function runQueuedImmediateCallbacks() {
133-
baseline.push(`Before running ${host.immediateCallbacks.log()}`);
134-
originalRunQueuedImmediateCallbacks.call(host);
135-
baseline.push(`After running ${host.immediateCallbacks.log()}`);
136-
}
137115
}
138116

139117
export interface BaselineBase {
140118
baseline: string[];
141119
sys: TscWatchSystem;
142-
oldSnap: SystemSnap;
143120
}
144121

145122
export interface Baseline extends BaselineBase, CommandLineCallbacks {
@@ -153,9 +130,9 @@ export function createBaseline(system: TestServerHost, modifySystem?: (sys: Test
153130
const sys = changeToTestServerHostWithTimeoutLogging(changeToHostTrackingWrittenFiles(initialSys), baseline);
154131
baseline.push(`currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}`);
155132
baseline.push("Input::");
156-
sys.diff(baseline);
133+
sys.serializeState(baseline, SerializeOutputOrder.None);
157134
const { cb, getPrograms } = commandLineCallbacks(sys);
158-
return { sys, baseline, oldSnap: sys.snap(), cb, getPrograms };
135+
return { sys, baseline, cb, getPrograms };
159136
}
160137

161138
export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) {
@@ -208,13 +185,10 @@ function updateWatchHostForBaseline<T extends ts.BuilderProgram>(host: ts.WatchC
208185
}
209186

210187
export function applyEdit(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], edit: TscWatchCompileChange["edit"], caption?: TscWatchCompileChange["caption"]) {
211-
const oldSnap = sys.snap();
212188
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
213189
edit(sys);
214190
baseline.push("Input::");
215-
sys.diff(baseline, oldSnap);
216-
sys.serializeWatches(baseline);
217-
return sys.snap();
191+
sys.serializeState(baseline, SerializeOutputOrder.AfterDiff);
218192
}
219193

220194
export interface RunWatchBaseline<T extends ts.BuilderProgram> extends BaselineBase, TscWatchCompileBase<T> {
@@ -230,7 +204,6 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
230204
getPrograms,
231205
sys,
232206
baseline,
233-
oldSnap,
234207
baselineSourceMap,
235208
baselineDependencies,
236209
edits,
@@ -243,21 +216,19 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
243216
getPrograms,
244217
oldPrograms: ts.emptyArray,
245218
sys,
246-
oldSnap,
247219
baselineSourceMap,
248220
baselineDependencies,
249221
});
250222

251223
if (edits) {
252224
for (const { caption, edit, timeouts, symlinksNotReflected, skipStructureCheck } of edits) {
253-
oldSnap = applyEdit(sys, baseline, edit, caption);
225+
applyEdit(sys, baseline, edit, caption);
254226
timeouts(sys, programs, watchOrSolution);
255227
programs = watchBaseline({
256228
baseline,
257229
getPrograms,
258230
oldPrograms: programs,
259231
sys,
260-
oldSnap,
261232
baselineSourceMap,
262233
baselineDependencies,
263234
caption,
@@ -291,7 +262,6 @@ export function watchBaseline({
291262
getPrograms,
292263
oldPrograms,
293264
sys,
294-
oldSnap,
295265
baselineSourceMap,
296266
baselineDependencies,
297267
caption,
@@ -300,21 +270,18 @@ export function watchBaseline({
300270
symlinksNotReflected,
301271
}: WatchBaseline) {
302272
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
303-
sys.serializeOutput(baseline);
304273
const programs = getPrograms();
305-
baselinePrograms(baseline, programs, oldPrograms, baselineDependencies);
306-
sys.serializeWatches(baseline);
307-
baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, "");
308-
sys.diff(baseline, oldSnap);
309274
sys.writtenFiles.forEach((value, key) => {
310275
assert.equal(value, 1, `Expected to write file ${key} only once`);
311276
});
277+
sys.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
278+
baselinePrograms(baseline, programs, oldPrograms, baselineDependencies);
279+
baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, "");
312280
// Verify program structure and resolution cache when incremental edit with tsc --watch (without build mode)
313281
if (resolutionCache && programs.length) {
314282
ts.Debug.assert(programs.length === 1);
315283
verifyProgramStructureAndResolutionCache(caption!, sys, programs[0][0], resolutionCache, useSourceOfProjectReferenceRedirect, symlinksNotReflected);
316284
}
317-
sys.writtenFiles.clear();
318285
return programs;
319286
}
320287
function verifyProgramStructureAndResolutionCache(

0 commit comments

Comments
 (0)