move snap/diff out of tsserver

This commit is contained in:
Nathan Shively-Sanders
2022-06-09 11:23:08 -07:00
parent 8be58eb472
commit e23c64b68a
7 changed files with 114 additions and 113 deletions
+92
View File
@@ -588,6 +588,98 @@ interface Array<T> { length: number; [n: number]: T; }`
}
}
export function snap(fshost: VirtualFS.VirtualServerHost): ESMap<Path, FSEntry> {
const result = new Map<Path, FSEntry>();
fshost.fs.forEach((value, key) => {
const cloneValue = clone(value);
if (isFsFolder(cloneValue)) {
cloneValue.entries = cloneValue.entries.map(clone) as SortedArray<FSEntry>;
}
result.set(key, cloneValue);
});
return result;
}
export function diff(fshost: VirtualFS.VirtualServerHost, baseline: string[], base: ESMap<string, FSEntry> = new Map()) {
fshost.fs.forEach(newFsEntry => {
diffFsEntry(baseline, base.get(newFsEntry.path), newFsEntry, fshost.writtenFiles);
});
base.forEach(oldFsEntry => {
const newFsEntry = fshost.fs.get(oldFsEntry.path);
if (!newFsEntry) {
diffFsEntry(baseline, oldFsEntry, newFsEntry, fshost.writtenFiles);
}
});
baseline.push("");
}
function diffFsFile(baseline: string[], fsEntry: FsFile) {
baseline.push(`//// [${fsEntry.fullPath}]\r\n${fsEntry.content}`, "");
}
function diffFsSymLink(baseline: string[], fsEntry: FsSymLink) {
baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})`);
}
function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsEntry: FSEntry | undefined, writtenFiles: ESMap<string, any> | undefined): void {
const file = newFsEntry && newFsEntry.fullPath;
if (isFsFile(oldFsEntry)) {
if (isFsFile(newFsEntry)) {
if (oldFsEntry.content !== newFsEntry.content) {
diffFsFile(baseline, newFsEntry);
}
else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) {
if (oldFsEntry.fullPath !== newFsEntry.fullPath) {
baseline.push(`//// [${file}] file was renamed from file ${oldFsEntry.fullPath}`);
}
else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) {
baseline.push(`//// [${file}] file changed its modified time`);
}
else {
baseline.push(`//// [${file}] file written with same contents`);
}
}
}
else {
baseline.push(`//// [${oldFsEntry.fullPath}] deleted`);
if (isFsSymLink(newFsEntry)) {
diffFsSymLink(baseline, newFsEntry);
}
}
}
else if (isFsSymLink(oldFsEntry)) {
if (isFsSymLink(newFsEntry)) {
if (oldFsEntry.symLink !== newFsEntry.symLink) {
diffFsSymLink(baseline, newFsEntry);
}
else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) {
if (oldFsEntry.fullPath !== newFsEntry.fullPath) {
baseline.push(`//// [${file}] symlink was renamed from symlink ${oldFsEntry.fullPath}`);
}
else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) {
baseline.push(`//// [${file}] symlink changed its modified time`);
}
else {
baseline.push(`//// [${file}] symlink written with same link`);
}
}
}
else {
baseline.push(`//// [${oldFsEntry.fullPath}] deleted symlink`);
if (isFsFile(newFsEntry)) {
diffFsFile(baseline, newFsEntry);
}
}
}
else if (isFsFile(newFsEntry)) {
diffFsFile(baseline, newFsEntry);
}
else if (isFsSymLink(newFsEntry)) {
diffFsSymLink(baseline, newFsEntry);
}
}
function serializeTestFsWatcher({ directoryName, fallbackPollingInterval, fallbackOptions }: VirtualFsWatcher) {
return {
directoryName,
+6 -6
View File
@@ -234,7 +234,7 @@ namespace ts {
const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json");
const testsIndex = getTsBuildProjectFile("tests", "index.ts");
const baseline: string[] = [];
let oldSnap: ReturnType<VirtualFS.TestServerHost["snap"]> | undefined;
let oldSnap: ReturnType<typeof VirtualFS.snap> | undefined;
const system = VirtualFS.changeToHostTrackingWrittenFiles(
fakes.patchHostForBuildInfoReadWrite(
tscWatch.createWatchedSystem([
@@ -265,9 +265,9 @@ namespace ts {
function baselineState() {
system.serializeOutput(baseline);
system.diff(baseline, oldSnap);
VirtualFS.diff(system, baseline, oldSnap);
system.writtenFiles.clear();
oldSnap = system.snap();
oldSnap = VirtualFS.snap(system);
}
});
@@ -305,7 +305,7 @@ namespace ts {
const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json");
const testsIndex = getTsBuildProjectFile("tests", "index.ts");
const baseline: string[] = [];
let oldSnap: ReturnType<VirtualFS.TestServerHost["snap"]> | undefined;
let oldSnap: ReturnType<typeof VirtualFS.snap> | undefined;
const system = VirtualFS.changeToHostTrackingWrittenFiles(
fakes.patchHostForBuildInfoReadWrite(
tscWatch.createWatchedSystem([
@@ -349,9 +349,9 @@ namespace ts {
function baselineState(heading: string) {
baseline.push(heading);
system.serializeOutput(baseline);
system.diff(baseline, oldSnap);
VirtualFS.diff(system, baseline, oldSnap);
system.writtenFiles.clear();
oldSnap = system.snap();
oldSnap = VirtualFS.snap(system);
}
});
});
+7 -7
View File
@@ -129,7 +129,7 @@ namespace ts.tscWatch {
timeouts: sys => sys.checkTimeoutQueueLength(0),
};
export type SystemSnap = ReturnType<WatchedSystem["snap"]>;
export type SystemSnap = ReturnType<typeof VirtualFS.snap>;
function tscWatchCompile(input: TscWatchCompile) {
it("tsc-watch:: Generates files matching the baseline", () => {
const { sys, baseline, oldSnap } = createBaseline(input.sys());
@@ -178,9 +178,9 @@ namespace ts.tscWatch {
const sys = VirtualFS.changeToHostTrackingWrittenFiles(initialSys);
const baseline: string[] = [];
baseline.push("Input::");
sys.diff(baseline);
VirtualFS.diff(sys, baseline);
const { cb, getPrograms } = commandLineCallbacks(sys);
return { sys, baseline, oldSnap: sys.snap(), cb, getPrograms };
return { sys, baseline, oldSnap: VirtualFS.snap(sys), cb, getPrograms };
}
export function createSolutionBuilderWithWatchHostForBaseline(sys: WatchedSystem, cb: ExecuteCommandLineCallbacks) {
@@ -238,12 +238,12 @@ namespace ts.tscWatch {
}
export function applyChange(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], change: TscWatchCompileChange["change"], caption?: TscWatchCompileChange["caption"]) {
const oldSnap = sys.snap();
const oldSnap = VirtualFS.snap(sys);
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
change(sys);
baseline.push("Input::");
sys.diff(baseline, oldSnap);
return sys.snap();
VirtualFS.diff(sys, baseline, oldSnap);
return VirtualFS.snap(sys);
}
export interface RunWatchBaseline<T extends BuilderProgram> extends BaselineBase, TscWatchCompileBase<T> {
@@ -302,7 +302,7 @@ namespace ts.tscWatch {
const programs = baselinePrograms(baseline, getPrograms, oldPrograms, baselineDependencies);
sys.serializeWatches(baseline);
baseline.push(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}`, "");
sys.diff(baseline, oldSnap);
VirtualFS.diff(sys, baseline, oldSnap);
sys.writtenFiles.forEach((value, key) => {
assert.equal(value, 1, `Expected to write file ${key} only once`);
});
@@ -545,7 +545,7 @@ export class A {
});
const {cb: cb2, getPrograms: getPrograms2 } = commandLineCallbacks(sys);
const oldSnap2 = sys.snap();
const oldSnap2 = VirtualFS.snap(sys);
baseline.push("createing separate watcher");
createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
rootFiles:[file1.path],
@@ -210,7 +210,7 @@ namespace ts.tscWatch {
) {
const { cb, getPrograms } = commandLineCallbacks(sys);
baseline.push(`tsc --w${optionsToExtend?.noEmit ? " --noEmit" : ""}`);
const oldSnap = sys.snap();
const oldSnap = VirtualFS.snap(sys);
const host = createWatchCompilerHostOfConfigFileForBaseline<T>({
configFileName: config.path,
optionsToExtend,
@@ -385,7 +385,7 @@ namespace ts.tscWatch {
applyChange(sys, baseline, sys => sys.writeFile(mainFile.path, "export const x = 10;"), "Fix error");
const { cb, getPrograms } = commandLineCallbacks(sys);
const oldSnap = sys.snap();
const oldSnap = VirtualFS.snap(sys);
const reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
const reportWatchStatus = createWatchStatusReporter(sys, /*pretty*/ true);
const host = createWatchCompilerHostOfConfigFile({
@@ -41,13 +41,13 @@ ${file.fileContent}`;
}
function baselineFileSystem(scenario: string, subScenario: string, requests: [string, Partial<protocol.Request>][], host: VirtualFS.VirtualServerHost, session: TestSession) {
const history: string[] = [];
let prev = host.snap();
let prev = VirtualFS.snap(host);
for (const [name, request] of requests) {
session.executeCommandSeq(request);
history.push("");
history.push("#### " + name);
host.diff(history, prev);
prev = host.snap();
VirtualFS.diff(host, history, prev);
prev = VirtualFS.snap(host);
}
Harness.Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.txt`, history.join("\r\n"));
baselineTsserverLogs(scenario, subScenario, session);
+3 -94
View File
@@ -125,7 +125,7 @@ namespace ts.VirtualFS {
export class VirtualServerHost implements FormatDiagnosticsHost, ModuleResolutionHost {
args: string[] = [];
protected fs: ESMap<Path, FSEntry> = new Map();
fs: ESMap<Path, FSEntry> = new Map();
getCanonicalFileName: (s: string) => string;
protected toPath: (f: string) => Path;
@@ -593,6 +593,8 @@ namespace ts.VirtualFS {
// Do nothing
}
writtenFiles!: ESMap<Path, number>;
realpath(s: string): string {
const fullPath = this.toNormalizedAbsolutePath(s);
const path = this.toPath(fullPath);
@@ -624,98 +626,5 @@ namespace ts.VirtualFS {
getEnvironmentVariable(_name: string) {
return "";
}
snap(): ESMap<Path, FSEntry> {
const result = new Map<Path, FSEntry>();
this.fs.forEach((value, key) => {
const cloneValue = clone(value);
if (isFsFolder(cloneValue)) {
cloneValue.entries = cloneValue.entries.map(clone) as SortedArray<FSEntry>;
}
result.set(key, cloneValue);
});
return result;
}
writtenFiles?: ESMap<Path, number>;
diff(baseline: string[], base: ESMap<string, FSEntry> = new Map()) {
this.fs.forEach(newFsEntry => {
diffFsEntry(baseline, base.get(newFsEntry.path), newFsEntry, this.writtenFiles);
});
base.forEach(oldFsEntry => {
const newFsEntry = this.fs.get(oldFsEntry.path);
if (!newFsEntry) {
diffFsEntry(baseline, oldFsEntry, newFsEntry, this.writtenFiles);
}
});
baseline.push("");
}
}
function diffFsFile(baseline: string[], fsEntry: FsFile) {
baseline.push(`//// [${fsEntry.fullPath}]\r\n${fsEntry.content}`, "");
}
function diffFsSymLink(baseline: string[], fsEntry: FsSymLink) {
baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})`);
}
function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsEntry: FSEntry | undefined, writtenFiles: ESMap<string, any> | undefined): void {
const file = newFsEntry && newFsEntry.fullPath;
if (isFsFile(oldFsEntry)) {
if (isFsFile(newFsEntry)) {
if (oldFsEntry.content !== newFsEntry.content) {
diffFsFile(baseline, newFsEntry);
}
else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) {
if (oldFsEntry.fullPath !== newFsEntry.fullPath) {
baseline.push(`//// [${file}] file was renamed from file ${oldFsEntry.fullPath}`);
}
else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) {
baseline.push(`//// [${file}] file changed its modified time`);
}
else {
baseline.push(`//// [${file}] file written with same contents`);
}
}
}
else {
baseline.push(`//// [${oldFsEntry.fullPath}] deleted`);
if (isFsSymLink(newFsEntry)) {
diffFsSymLink(baseline, newFsEntry);
}
}
}
else if (isFsSymLink(oldFsEntry)) {
if (isFsSymLink(newFsEntry)) {
if (oldFsEntry.symLink !== newFsEntry.symLink) {
diffFsSymLink(baseline, newFsEntry);
}
else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) {
if (oldFsEntry.fullPath !== newFsEntry.fullPath) {
baseline.push(`//// [${file}] symlink was renamed from symlink ${oldFsEntry.fullPath}`);
}
else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) {
baseline.push(`//// [${file}] symlink changed its modified time`);
}
else {
baseline.push(`//// [${file}] symlink written with same link`);
}
}
}
else {
baseline.push(`//// [${oldFsEntry.fullPath}] deleted symlink`);
if (isFsFile(newFsEntry)) {
diffFsFile(baseline, newFsEntry);
}
}
}
else if (isFsFile(newFsEntry)) {
diffFsFile(baseline, newFsEntry);
}
else if (isFsSymLink(newFsEntry)) {
diffFsSymLink(baseline, newFsEntry);
}
}
}