mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
move snap/diff out of tsserver
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user