mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Testing WIP
This commit is contained in:
parent
6d04378e90
commit
76d2ba64df
@ -317,16 +317,12 @@ namespace ts {
|
||||
return date2 > date1 ? date2 : date1;
|
||||
}
|
||||
|
||||
function older(date1: Date, date2: Date): Date {
|
||||
return date2 < date1 ? date2 : date1;
|
||||
}
|
||||
|
||||
function isDeclarationFile(fileName: string) {
|
||||
return fileExtensionIs(fileName, ".d.ts");
|
||||
}
|
||||
|
||||
export function createBuildContext(options: BuildOptions): BuildContext {
|
||||
const verboseDiag = options.verbose && createDiagnosticReporter(sys, /*pretty*/ false);
|
||||
export function createBuildContext(options: BuildOptions, reportDiagnostic: DiagnosticReporter): BuildContext {
|
||||
const verboseDiag = options.verbose && reportDiagnostic;
|
||||
return {
|
||||
options,
|
||||
projectStatus: createFileMap(),
|
||||
@ -371,8 +367,7 @@ namespace ts {
|
||||
addProject(".");
|
||||
}
|
||||
|
||||
const context = createBuildContext({ verbose, dry, force });
|
||||
const builder = createSolutionBuilder(host, reportDiagnostic, context);
|
||||
const builder = createSolutionBuilder(host, reportDiagnostic, { verbose, dry, force });
|
||||
if (clean) {
|
||||
builder.cleanProjects(projects);
|
||||
}
|
||||
@ -391,8 +386,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function createSolutionBuilder(host: CompilerHost, reportDiagnostic: DiagnosticReporter, context: BuildContext) {
|
||||
export function createSolutionBuilder(host: CompilerHost, reportDiagnostic: DiagnosticReporter, options: BuildOptions) {
|
||||
const configFileCache = createConfigFileCache(host);
|
||||
let context: BuildContext = undefined!;
|
||||
|
||||
return {
|
||||
getUpToDateStatus,
|
||||
@ -473,7 +469,7 @@ namespace ts {
|
||||
oldestOutputFileTime = outputTime;
|
||||
oldestOutputFileName = output;
|
||||
}
|
||||
newestOutputFileTime = older(newestOutputFileTime, outputTime);
|
||||
newestOutputFileTime = newer(newestOutputFileTime, outputTime);
|
||||
|
||||
// Keep track of when the most recent time a .d.ts file was changed.
|
||||
// In addition to file timestamps, we also keep track of when a .d.ts file
|
||||
@ -709,6 +705,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function cleanProjects(configFileNames: string[]) {
|
||||
context = createBuildContext(options, reportDiagnostic);
|
||||
|
||||
// Get the same graph for cleaning we'd use for building
|
||||
const graph = createDependencyGraph(configFileNames);
|
||||
|
||||
@ -736,6 +734,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function buildProjects(configFileNames: string[]) {
|
||||
context = createBuildContext(options, reportDiagnostic);
|
||||
|
||||
const resolvedNames: string[] = [];
|
||||
for (const name of configFileNames) {
|
||||
let fullPath = resolvePath(host.getCurrentDirectory(), name);
|
||||
@ -823,7 +823,7 @@ namespace ts {
|
||||
context.verbose(Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, configFileName, status.missingOutputFileName);
|
||||
return;
|
||||
case UpToDateStatusType.UpToDate:
|
||||
context.verbose(Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFileName, status.newestDeclarationFileContentChangedTime as any, status.newestOutputFileTime);
|
||||
context.verbose(Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFileName, status.newestInputFileTime, status.newestOutputFileTime);
|
||||
return;
|
||||
case UpToDateStatusType.UpToDateWithUpstreamTypes:
|
||||
context.verbose(Diagnostics.Project_0_is_up_to_date_with_its_upstream_types, configFileName);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
namespace ts {
|
||||
let currentTime = 100;
|
||||
const bfs = new vfs.FileSystem(/*ignoreCase*/ false, { time });
|
||||
const lastDiagnostics: Diagnostic[] = [];
|
||||
let lastDiagnostics: Diagnostic[] = [];
|
||||
const reportDiagnostic: DiagnosticReporter = diagnostic => lastDiagnostics.push(diagnostic);
|
||||
|
||||
const sampleRoot = resolvePath(__dirname, "../../tests/projects/sample1");
|
||||
@ -12,47 +12,109 @@ namespace ts {
|
||||
bfs.writeFileSync("/lib/lib.d.ts", Harness.IO.readFile(combinePaths(Harness.libFolder, "lib.d.ts")));
|
||||
bfs.meta.set("defaultLibLocation", "/lib");
|
||||
bfs.makeReadonly();
|
||||
tick();
|
||||
|
||||
describe("tsbuild tests", () => {
|
||||
it("builds the referenced project", () => {
|
||||
it("can build the sample project 'tests' without error", () => {
|
||||
const fs = bfs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, reportDiagnostic, createBuildContext({ dry: false, force: false, verbose: false }));
|
||||
const builder = createSolutionBuilder(host, reportDiagnostic, { dry: false, force: false, verbose: false });
|
||||
|
||||
fs.chdir("/src/tests");
|
||||
fs.debugPrint();
|
||||
builder.buildProjects(["."]);
|
||||
printDiagnostics();
|
||||
fs.debugPrint();
|
||||
assertDiagnosticMessages(Diagnostics.File_0_does_not_exist);
|
||||
assertDiagnosticMessages(/*empty*/);
|
||||
});
|
||||
|
||||
it("can detect when and what to rebuild", () => {
|
||||
const fs = bfs.shadow();
|
||||
const host = new fakes.CompilerHost(fs);
|
||||
const builder = createSolutionBuilder(host, reportDiagnostic, { dry: false, force: false, verbose: true });
|
||||
|
||||
fs.chdir("/src/tests");
|
||||
builder.buildProjects(["."]);
|
||||
assertDiagnosticMessages(Diagnostics.Sorted_list_of_input_projects_Colon_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
|
||||
Diagnostics.Building_project_0);
|
||||
tick();
|
||||
|
||||
// All three projects are up to date
|
||||
clearDiagnostics();
|
||||
builder.buildProjects(["."]);
|
||||
assertDiagnosticMessages(Diagnostics.Sorted_list_of_input_projects_Colon_0,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2);
|
||||
tick();
|
||||
|
||||
// Update a file in the leaf node (tests), only it should rebuild the last one
|
||||
clearDiagnostics();
|
||||
fs.writeFileSync("/src/tests/index.ts", "const m = 10;");
|
||||
builder.buildProjects(["."]);
|
||||
|
||||
assertDiagnosticMessages(Diagnostics.Sorted_list_of_input_projects_Colon_0,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
|
||||
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
|
||||
Diagnostics.Building_project_0);
|
||||
tick();
|
||||
|
||||
// Update a file in the parent (without affecting types), should get fast downstream builds
|
||||
clearDiagnostics();
|
||||
replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET");
|
||||
builder.buildProjects(["."]);
|
||||
|
||||
assertDiagnosticMessages(Diagnostics.Sorted_list_of_input_projects_Colon_0,
|
||||
Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
|
||||
Diagnostics.Building_project_0,
|
||||
Diagnostics.Project_0_is_up_to_date_with_its_upstream_types,
|
||||
Diagnostics.Updating_output_timestamps_of_project_0,
|
||||
Diagnostics.Project_0_is_up_to_date_with_its_upstream_types,
|
||||
Diagnostics.Updating_output_timestamps_of_project_0);
|
||||
});
|
||||
});
|
||||
|
||||
function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
const old = fs.readFileSync(path, 'utf-8');
|
||||
if (old.indexOf(oldText) < 0) {
|
||||
throw new Error(`Text "${oldText}" does not exist in file ${path}`);
|
||||
}
|
||||
const newContent = old.replace(oldText, newText);
|
||||
fs.writeFileSync(path, newContent, 'utf-8');
|
||||
}
|
||||
|
||||
function assertDiagnosticMessages(...expected: DiagnosticMessage[]) {
|
||||
const actual = lastDiagnostics.slice();
|
||||
actual.sort((a, b) => b.code - a.code);
|
||||
expected.sort((a, b) => b.code - a.code);
|
||||
if (actual.length !== expected.length) {
|
||||
assert.fail<any>(actual, expected, `Diagnostic arrays did not match - expected ${actual.join(",")}, got ${expected.join(",")}`);
|
||||
assert.fail<any>(actual, expected, `Diagnostic arrays did not match - expected\r\n${actual.map(a => " " + a.messageText).join("\r\n")}\r\ngot\r\n${expected.map(e => " " + e.message).join("\r\n")}`);
|
||||
}
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
if (actual[i].code !== expected[i].code) {
|
||||
assert.fail(actual[i].messageText, expected[i].message, "Mismatched error code");
|
||||
assert.fail(actual[i].messageText, expected[i].message, `Mismatched error code - expected diagnostic ${i} "${actual[i].messageText}" to match ${expected[i].message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function printDiagnostics() {
|
||||
function clearDiagnostics() {
|
||||
lastDiagnostics = [];
|
||||
}
|
||||
|
||||
export function printDiagnostics(header = "== Diagnostics ==") {
|
||||
const out = createDiagnosticReporter(sys);
|
||||
sys.write(header + "\r\n");
|
||||
for (const d of lastDiagnostics) {
|
||||
out(d);
|
||||
}
|
||||
}
|
||||
|
||||
function tick() {
|
||||
currentTime += 10;
|
||||
currentTime += 100000;
|
||||
}
|
||||
function time() {
|
||||
return currentTime;
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export const someString: string = "HELLO WORLD";
|
||||
export function leftPad(s: string, n: number) { return s + n; }
|
||||
export function multiply(a: number, b: number) { return a * b; }
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
{
|
||||
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import * as c from '../core';
|
||||
import * as c from '../core/index';
|
||||
export function getSecondsInDay() {
|
||||
return c.multiply(10, 15);
|
||||
}
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"declaration": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../core" }
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import * as c from '../core';
|
||||
import * as logic from '../logic';
|
||||
import * as c from '../core/index';
|
||||
import * as logic from '../logic/index';
|
||||
|
||||
c.leftPad("", 10);
|
||||
logic.getSecondsInDay();
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
"references": [
|
||||
{ "path": "../core" },
|
||||
{ "path": "../logic" }
|
||||
]
|
||||
],
|
||||
"files": ["index.ts"]
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"references": [
|
||||
{ "path": "../logic" }
|
||||
{ "path": "../logic/index" }
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user