mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-07 05:41:22 -06:00
Write first test with --build and --watch
This commit is contained in:
parent
13bd4788d9
commit
17ee9231b7
@ -66,20 +66,20 @@ namespace ts {
|
||||
mtime: Date;
|
||||
}
|
||||
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
|
||||
const existingDirectories = createMap<boolean>();
|
||||
|
||||
function getCanonicalFileName(fileName: string): string {
|
||||
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
|
||||
// otherwise use toLowerCase as a canonical form.
|
||||
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
performance.mark("beforeIORead");
|
||||
text = sys.readFile(fileName, options.charset);
|
||||
text = system.readFile(fileName, options.charset);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
@ -97,7 +97,7 @@ namespace ts {
|
||||
if (existingDirectories.has(directoryPath)) {
|
||||
return true;
|
||||
}
|
||||
if (sys.directoryExists(directoryPath)) {
|
||||
if (system.directoryExists(directoryPath)) {
|
||||
existingDirectories.set(directoryPath, true);
|
||||
return true;
|
||||
}
|
||||
@ -108,7 +108,7 @@ namespace ts {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
|
||||
const parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
sys.createDirectory(directoryPath);
|
||||
system.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,8 +119,8 @@ namespace ts {
|
||||
outputFingerprints = createMap<OutputFingerprint>();
|
||||
}
|
||||
|
||||
const hash = sys.createHash!(data); // TODO: GH#18217
|
||||
const mtimeBefore = sys.getModifiedTime!(fileName); // TODO: GH#18217
|
||||
const hash = system.createHash!(data); // TODO: GH#18217
|
||||
const mtimeBefore = system.getModifiedTime!(fileName); // TODO: GH#18217
|
||||
|
||||
if (mtimeBefore) {
|
||||
const fingerprint = outputFingerprints.get(fileName);
|
||||
@ -133,9 +133,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
system.writeFile(fileName, data, writeByteOrderMark);
|
||||
|
||||
const mtimeAfter = sys.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217
|
||||
const mtimeAfter = system.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217
|
||||
|
||||
outputFingerprints.set(fileName, {
|
||||
hash,
|
||||
@ -149,11 +149,11 @@ namespace ts {
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
|
||||
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
|
||||
writeFileIfUpdated(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
else {
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
system.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
performance.mark("afterIOWrite");
|
||||
@ -167,32 +167,32 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDefaultLibLocation(): string {
|
||||
return getDirectoryPath(normalizePath(sys.getExecutingFilePath()));
|
||||
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
|
||||
}
|
||||
|
||||
const newLine = getNewLineCharacter(options);
|
||||
const realpath = sys.realpath && ((path: string) => sys.realpath!(path));
|
||||
const realpath = system.realpath && ((path: string) => system.realpath!(path));
|
||||
|
||||
return {
|
||||
getSourceFile,
|
||||
getDefaultLibLocation,
|
||||
getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)),
|
||||
writeFile,
|
||||
getCurrentDirectory: memoize(() => sys.getCurrentDirectory()),
|
||||
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
|
||||
getCurrentDirectory: memoize(() => system.getCurrentDirectory()),
|
||||
useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames,
|
||||
getCanonicalFileName,
|
||||
getNewLine: () => newLine,
|
||||
fileExists: fileName => sys.fileExists(fileName),
|
||||
readFile: fileName => sys.readFile(fileName),
|
||||
trace: (s: string) => sys.write(s + newLine),
|
||||
directoryExists: directoryName => sys.directoryExists(directoryName),
|
||||
getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "",
|
||||
getDirectories: (path: string) => sys.getDirectories(path),
|
||||
fileExists: fileName => system.fileExists(fileName),
|
||||
readFile: fileName => system.readFile(fileName),
|
||||
trace: (s: string) => system.write(s + newLine),
|
||||
directoryExists: directoryName => system.directoryExists(directoryName),
|
||||
getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : "",
|
||||
getDirectories: (path: string) => system.getDirectories(path),
|
||||
realpath,
|
||||
readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth),
|
||||
getModifiedTime: sys.getModifiedTime && (path => sys.getModifiedTime!(path)),
|
||||
setModifiedTime: sys.setModifiedTime && ((path, date) => sys.setModifiedTime!(path, date)),
|
||||
deleteFile: sys.deleteFile && (path => sys.deleteFile!(path))
|
||||
readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth),
|
||||
getModifiedTime: system.getModifiedTime && (path => system.getModifiedTime!(path)),
|
||||
setModifiedTime: system.setModifiedTime && ((path, date) => system.setModifiedTime!(path, date)),
|
||||
deleteFile: system.deleteFile && (path => system.deleteFile!(path))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -620,14 +620,14 @@ interface Array<T> {}`
|
||||
}
|
||||
}
|
||||
|
||||
removeFile(filePath: string) {
|
||||
deleteFile(filePath: string) {
|
||||
const path = this.toFullPath(filePath);
|
||||
const currentEntry = this.fs.get(path) as FsFile;
|
||||
Debug.assert(isFsFile(currentEntry));
|
||||
this.removeFileOrFolder(currentEntry, returnFalse);
|
||||
}
|
||||
|
||||
removeFolder(folderPath: string, recursive?: boolean) {
|
||||
deleteFolder(folderPath: string, recursive?: boolean) {
|
||||
const path = this.toFullPath(folderPath);
|
||||
const currentEntry = this.fs.get(path) as FsFolder;
|
||||
Debug.assert(isFsFolder(currentEntry));
|
||||
@ -635,7 +635,7 @@ interface Array<T> {}`
|
||||
const subEntries = currentEntry.entries.slice();
|
||||
subEntries.forEach(fsEntry => {
|
||||
if (isFsFolder(fsEntry)) {
|
||||
this.removeFolder(fsEntry.fullPath, recursive);
|
||||
this.deleteFolder(fsEntry.fullPath, recursive);
|
||||
}
|
||||
else {
|
||||
this.removeFileOrFolder(fsEntry, returnFalse);
|
||||
@ -766,6 +766,14 @@ interface Array<T> {}`
|
||||
return (fsEntry && fsEntry.modifiedTime)!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
setModifiedTime(s: string, date: Date) {
|
||||
const path = this.toFullPath(s);
|
||||
const fsEntry = this.fs.get(path);
|
||||
if (fsEntry) {
|
||||
fsEntry.modifiedTime = date;
|
||||
}
|
||||
}
|
||||
|
||||
readFile(s: string): string | undefined {
|
||||
const fsEntry = this.getRealFile(this.toFullPath(s));
|
||||
return fsEntry ? fsEntry.content : undefined;
|
||||
|
||||
@ -80,6 +80,7 @@
|
||||
"unittests/transform.ts",
|
||||
"unittests/transpile.ts",
|
||||
"unittests/tsbuild.ts",
|
||||
"unittests/tsbuildWatchMode.ts",
|
||||
"unittests/tsconfigParsing.ts",
|
||||
"unittests/tscWatchMode.ts",
|
||||
"unittests/versionCache.ts",
|
||||
|
||||
69
src/testRunner/unittests/tsbuildWatchMode.ts
Normal file
69
src/testRunner/unittests/tsbuildWatchMode.ts
Normal file
@ -0,0 +1,69 @@
|
||||
namespace ts.tscWatch {
|
||||
export import libFile = TestFSWithWatch.libFile;
|
||||
function createSolutionBuilder(host: WatchedSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
|
||||
const compilerHost = createCompilerHost({}, /*setParentNodes*/ undefined, host);
|
||||
const reportDiag = createDiagnosticReporter(host);
|
||||
const report = (message: DiagnosticMessage, ...args: string[]) => reportDiag(createCompilerDiagnostic(message, ...args));
|
||||
const buildHost: BuildHost = {
|
||||
error: report,
|
||||
verbose: report,
|
||||
message: report,
|
||||
errorDiagnostic: d => reportDiag(d)
|
||||
};
|
||||
return ts.createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions || { dry: false, force: false, verbose: false }, host);
|
||||
}
|
||||
|
||||
function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
|
||||
const solutionBuilder = createSolutionBuilder(host, rootNames, defaultOptions);
|
||||
solutionBuilder.buildAllProjects();
|
||||
solutionBuilder.startWatching();
|
||||
return solutionBuilder;
|
||||
}
|
||||
|
||||
describe("tsbuild-watch program updates", () => {
|
||||
const projectsLocation = "/user/username/projects";
|
||||
const project = "sample1";
|
||||
const enum SubProject {
|
||||
core = "core",
|
||||
logic = "logic",
|
||||
tests = "tests",
|
||||
ui = "ui"
|
||||
}
|
||||
type ReadonlyFile = Readonly<File>;
|
||||
/** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */
|
||||
type SubProjectFiles = [ReadonlyFile, ReadonlyFile] | [ReadonlyFile, ReadonlyFile, ReadonlyFile, ReadonlyFile];
|
||||
const root = Harness.IO.getWorkspaceRoot();
|
||||
function projectFile(subProject: SubProject, baseFileName: string): File {
|
||||
return {
|
||||
path: `${projectsLocation}/${project}/${subProject}/${baseFileName.toLowerCase()}`,
|
||||
content: Harness.IO.readFile(`${root}/tests/projects/${project}/${subProject}/${baseFileName}`)!
|
||||
};
|
||||
}
|
||||
function subProjectFiles(subProject: SubProject, anotherModuleAndSomeDecl?: true): SubProjectFiles {
|
||||
const tsconfig = projectFile(subProject, "tsconfig.json");
|
||||
const index = projectFile(subProject, "index.ts");
|
||||
if (!anotherModuleAndSomeDecl) {
|
||||
return [tsconfig, index];
|
||||
}
|
||||
const anotherModule = projectFile(SubProject.core, "anotherModule.ts");
|
||||
const someDecl = projectFile(SubProject.core, "some_decl.ts");
|
||||
return [tsconfig, index, anotherModule, someDecl];
|
||||
}
|
||||
|
||||
const core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true);
|
||||
const logic = subProjectFiles(SubProject.logic);
|
||||
const tests = subProjectFiles(SubProject.tests);
|
||||
const ui = subProjectFiles(SubProject.ui);
|
||||
const allFiles: ReadonlyArray<File> = [libFile, ...core, ...logic, ...tests, ...ui];
|
||||
const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path);
|
||||
it("creates solution in watch mode", () => {
|
||||
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
|
||||
const originalWrite = host.write;
|
||||
host.write = s => { console.log(s); originalWrite.call(host, s); };
|
||||
createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]);
|
||||
checkWatchedFiles(host, testProjectExpectedWatchedFiles);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ true); // TODO: #26524
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1,17 +1,16 @@
|
||||
namespace ts.tscWatch {
|
||||
import WatchedSystem = TestFSWithWatch.TestServerHost;
|
||||
type File = TestFSWithWatch.File;
|
||||
type SymLink = TestFSWithWatch.SymLink;
|
||||
import createWatchedSystem = TestFSWithWatch.createWatchedSystem;
|
||||
import checkArray = TestFSWithWatch.checkArray;
|
||||
import libFile = TestFSWithWatch.libFile;
|
||||
import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
|
||||
import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed;
|
||||
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
|
||||
import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed;
|
||||
import checkOutputContains = TestFSWithWatch.checkOutputContains;
|
||||
import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;
|
||||
import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory;
|
||||
export import WatchedSystem = TestFSWithWatch.TestServerHost;
|
||||
export type File = TestFSWithWatch.File;
|
||||
export type SymLink = TestFSWithWatch.SymLink;
|
||||
export import createWatchedSystem = TestFSWithWatch.createWatchedSystem;
|
||||
export import checkArray = TestFSWithWatch.checkArray;
|
||||
export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
|
||||
export import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed;
|
||||
export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
|
||||
export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed;
|
||||
export import checkOutputContains = TestFSWithWatch.checkOutputContains;
|
||||
export import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;
|
||||
export import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory;
|
||||
|
||||
export function checkProgramActualFiles(program: Program, expectedFiles: string[]) {
|
||||
checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
|
||||
|
||||
@ -8257,7 +8257,7 @@ new C();`
|
||||
|
||||
verifyProjectWithResolvedModule(session);
|
||||
|
||||
host.removeFolder(recognizersTextDist, /*recursive*/ true);
|
||||
host.deleteFolder(recognizersTextDist, /*recursive*/ true);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
verifyProjectWithUnresolvedModule(session);
|
||||
@ -9173,7 +9173,7 @@ describe("Test Suite 1", () => {
|
||||
checkProjectActualFiles(project, expectedFilesWithUnitTest1);
|
||||
|
||||
const navBarResultUnitTest1 = navBarFull(session, unitTest1);
|
||||
host.removeFile(unitTest1.path);
|
||||
host.deleteFile(unitTest1.path);
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
checkProjectActualFiles(project, expectedFilesWithoutUnitTest1);
|
||||
|
||||
@ -9297,7 +9297,7 @@ export function Test2() {
|
||||
checkDeclarationFiles(bTs, session, [bDtsMap, bDts]);
|
||||
|
||||
// Testing what happens if we delete the original sources.
|
||||
host.removeFile(bTs.path);
|
||||
host.deleteFile(bTs.path);
|
||||
|
||||
openFilesForSession([userTs], session);
|
||||
const service = session.getProjectService();
|
||||
|
||||
@ -4125,7 +4125,7 @@ declare namespace ts {
|
||||
declare namespace ts {
|
||||
function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined;
|
||||
function resolveTripleslashReference(moduleName: string, containingFile: string): string;
|
||||
function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost;
|
||||
function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost;
|
||||
function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
interface FormatDiagnosticsHost {
|
||||
getCurrentDirectory(): string;
|
||||
|
||||
@ -4125,7 +4125,7 @@ declare namespace ts {
|
||||
declare namespace ts {
|
||||
function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined;
|
||||
function resolveTripleslashReference(moduleName: string, containingFile: string): string;
|
||||
function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost;
|
||||
function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean, system?: System): CompilerHost;
|
||||
function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
interface FormatDiagnosticsHost {
|
||||
getCurrentDirectory(): string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user