mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 10:29:18 -05:00
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
This commit is contained in:
@@ -94,6 +94,7 @@
|
||||
"unittests/tsbuild/amdModulesWithOut.ts",
|
||||
"unittests/tsbuild/containerOnlyReferenced.ts",
|
||||
"unittests/tsbuild/demo.ts",
|
||||
"unittests/tsbuild/emitDeclarationOnly.ts",
|
||||
"unittests/tsbuild/emptyFiles.ts",
|
||||
"unittests/tsbuild/graphOrdering.ts",
|
||||
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ts {
|
||||
[outputFiles[project.lib][ext.buildinfo], outputFiles[project.lib][ext.js], outputFiles[project.lib][ext.dts]],
|
||||
[outputFiles[project.app][ext.buildinfo], outputFiles[project.app][ext.js], outputFiles[project.app][ext.dts]]
|
||||
],
|
||||
lastProjectOutputJs: outputFiles[project.app][ext.js],
|
||||
lastProjectOutput: outputFiles[project.app][ext.js],
|
||||
initialBuild: {
|
||||
modifyFs
|
||||
},
|
||||
@@ -231,7 +231,7 @@ ${internal} export enum internalEnum { a, b, c }`);
|
||||
[libOutputFile[ext.buildinfo], libOutputFile[ext.js], libOutputFile[ext.dts]],
|
||||
[outputFiles[project.app][ext.buildinfo], outputFiles[project.app][ext.js], outputFiles[project.app][ext.dts]]
|
||||
],
|
||||
lastProjectOutputJs: outputFiles[project.app][ext.js],
|
||||
lastProjectOutput: outputFiles[project.app][ext.js],
|
||||
initialBuild: {
|
||||
modifyFs,
|
||||
expectedDiagnostics: [
|
||||
|
||||
109
src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts
Normal file
109
src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
const { time, tick } = getTime();
|
||||
before(() => {
|
||||
projFs = loadProjectFromDisk("tests/projects/emitDeclarationOnly", time);
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!;
|
||||
});
|
||||
|
||||
function verifyEmitDeclarationOnly(disableMap?: true) {
|
||||
verifyTsbuildOutput({
|
||||
scenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
|
||||
projFs: () => projFs,
|
||||
time,
|
||||
tick,
|
||||
proj: "emitDeclarationOnly",
|
||||
rootNames: ["/src"],
|
||||
lastProjectOutput: `/src/lib/index.d.ts`,
|
||||
outputFiles: [
|
||||
"/src/lib/a.d.ts",
|
||||
"/src/lib/b.d.ts",
|
||||
"/src/lib/c.d.ts",
|
||||
"/src/lib/index.d.ts",
|
||||
"/src/tsconfig.tsbuildinfo",
|
||||
...(disableMap ? emptyArray : [
|
||||
"/src/lib/a.d.ts.map",
|
||||
"/src/lib/b.d.ts.map",
|
||||
"/src/lib/c.d.ts.map",
|
||||
"/src/lib/index.d.ts.map"
|
||||
])
|
||||
],
|
||||
initialBuild: {
|
||||
modifyFs: disableMap ?
|
||||
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
|
||||
noop,
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
|
||||
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
|
||||
]
|
||||
},
|
||||
incrementalDtsChangedBuild: {
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
|
||||
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
|
||||
]
|
||||
},
|
||||
baselineOnly: true,
|
||||
verifyDiagnostics: true
|
||||
});
|
||||
}
|
||||
verifyEmitDeclarationOnly();
|
||||
verifyEmitDeclarationOnly(/*disableMap*/ true);
|
||||
|
||||
verifyTsbuildOutput({
|
||||
scenario: `only dts output in non circular imports project with emitDeclarationOnly`,
|
||||
projFs: () => projFs,
|
||||
time,
|
||||
tick,
|
||||
proj: "emitDeclarationOnly",
|
||||
rootNames: ["/src"],
|
||||
lastProjectOutput: `/src/lib/a.d.ts`,
|
||||
outputFiles: [
|
||||
"/src/lib/a.d.ts",
|
||||
"/src/lib/b.d.ts",
|
||||
"/src/lib/c.d.ts",
|
||||
"/src/tsconfig.tsbuildinfo",
|
||||
"/src/lib/a.d.ts.map",
|
||||
"/src/lib/b.d.ts.map",
|
||||
"/src/lib/c.d.ts.map",
|
||||
],
|
||||
initialBuild: {
|
||||
modifyFs: fs => {
|
||||
fs.rimrafSync("/src/src/index.ts");
|
||||
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
|
||||
},
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
|
||||
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
|
||||
]
|
||||
},
|
||||
incrementalDtsChangedBuild: {
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
|
||||
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
|
||||
]
|
||||
},
|
||||
incrementalDtsUnchangedBuild: {
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
|
||||
export interface A {`),
|
||||
expectedDiagnostics: [
|
||||
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
|
||||
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
|
||||
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
|
||||
]
|
||||
},
|
||||
baselineOnly: true,
|
||||
verifyDiagnostics: true
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -102,7 +102,22 @@ namespace ts {
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };`;
|
||||
|
||||
export function loadProjectFromDisk(root: string, time?: vfs.FileSystemOptions["time"]): vfs.FileSystem {
|
||||
export const symbolLibContent = `
|
||||
interface SymbolConstructor {
|
||||
readonly species: symbol;
|
||||
readonly toStringTag: symbol;
|
||||
}
|
||||
declare var Symbol: SymbolConstructor;
|
||||
interface Symbol {
|
||||
readonly [Symbol.toStringTag]: string;
|
||||
}
|
||||
`;
|
||||
|
||||
export function loadProjectFromDisk(
|
||||
root: string,
|
||||
time?: vfs.FileSystemOptions["time"],
|
||||
libContentToAppend?: string
|
||||
): vfs.FileSystem {
|
||||
const resolver = vfs.createResolver(Harness.IO);
|
||||
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
|
||||
files: {
|
||||
@@ -112,12 +127,31 @@ declare const console: { log(msg: any): void; };`;
|
||||
meta: { defaultLibLocation: "/lib" },
|
||||
time
|
||||
});
|
||||
fs.mkdirSync("/lib");
|
||||
fs.writeFileSync("/lib/lib.d.ts", libContent);
|
||||
fs.makeReadonly();
|
||||
addLibAndMakeReadonly(fs, libContentToAppend);
|
||||
return fs;
|
||||
}
|
||||
|
||||
export function loadProjectFromFiles(
|
||||
files: vfs.FileSet,
|
||||
time?: vfs.FileSystemOptions["time"],
|
||||
libContentToAppend?: string
|
||||
): vfs.FileSystem {
|
||||
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
|
||||
files,
|
||||
cwd: "/",
|
||||
meta: { defaultLibLocation: "/lib" },
|
||||
time
|
||||
});
|
||||
addLibAndMakeReadonly(fs, libContentToAppend);
|
||||
return fs;
|
||||
}
|
||||
|
||||
function addLibAndMakeReadonly(fs: vfs.FileSystem, libContentToAppend?: string) {
|
||||
fs.mkdirSync("/lib");
|
||||
fs.writeFileSync("/lib/lib.d.ts", libContentToAppend ? `${libContent}${libContentToAppend}` : libContent);
|
||||
fs.makeReadonly();
|
||||
}
|
||||
|
||||
export function verifyOutputsPresent(fs: vfs.FileSystem, outputs: readonly string[]) {
|
||||
for (const output of outputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
@@ -199,7 +233,7 @@ declare const console: { log(msg: any): void; };`;
|
||||
fs: vfs.FileSystem;
|
||||
tick: () => void;
|
||||
rootNames: readonly string[];
|
||||
expectedMapFileNames: readonly string[];
|
||||
expectedMapFileNames?: readonly string[];
|
||||
expectedBuildInfoFilesForSectionBaselines?: readonly BuildInfoSectionBaselineFiles[];
|
||||
modifyFs: (fs: vfs.FileSystem) => void;
|
||||
}
|
||||
@@ -221,7 +255,7 @@ declare const console: { log(msg: any): void; };`;
|
||||
return originalReadFile.call(host, path);
|
||||
};
|
||||
builder.build();
|
||||
generateSourceMapBaselineFiles(fs, expectedMapFileNames);
|
||||
if (expectedMapFileNames) generateSourceMapBaselineFiles(fs, expectedMapFileNames);
|
||||
generateBuildInfoSectionBaselineFiles(fs, expectedBuildInfoFilesForSectionBaselines || emptyArray);
|
||||
fs.makeReadonly();
|
||||
return { fs, actualReadFileMap, host, builder };
|
||||
@@ -267,9 +301,10 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
tick: () => void;
|
||||
proj: string;
|
||||
rootNames: readonly string[];
|
||||
expectedMapFileNames: readonly string[];
|
||||
/** map file names to generate baseline of */
|
||||
expectedMapFileNames?: readonly string[];
|
||||
expectedBuildInfoFilesForSectionBaselines?: readonly BuildInfoSectionBaselineFiles[];
|
||||
lastProjectOutputJs: string;
|
||||
lastProjectOutput: string;
|
||||
initialBuild: BuildState;
|
||||
outputFiles?: readonly string[];
|
||||
incrementalDtsChangedBuild?: BuildState;
|
||||
@@ -281,7 +316,7 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
|
||||
export function verifyTsbuildOutput({
|
||||
scenario, projFs, time, tick, proj, rootNames, outputFiles, baselineOnly, verifyDiagnostics,
|
||||
expectedMapFileNames, expectedBuildInfoFilesForSectionBaselines, lastProjectOutputJs,
|
||||
expectedMapFileNames, expectedBuildInfoFilesForSectionBaselines, lastProjectOutput,
|
||||
initialBuild, incrementalDtsChangedBuild, incrementalDtsUnchangedBuild, incrementalHeaderChangedBuild
|
||||
}: VerifyTsBuildInput) {
|
||||
describe(`tsc --b ${proj}:: ${scenario}`, () => {
|
||||
@@ -330,7 +365,7 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
let beforeBuildTime: number;
|
||||
let afterBuildTime: number;
|
||||
before(() => {
|
||||
beforeBuildTime = fs.statSync(lastProjectOutputJs).mtimeMs;
|
||||
beforeBuildTime = fs.statSync(lastProjectOutput).mtimeMs;
|
||||
tick();
|
||||
newFs = fs.shadow();
|
||||
tick();
|
||||
@@ -342,7 +377,7 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
expectedBuildInfoFilesForSectionBaselines,
|
||||
modifyFs: incrementalModifyFs,
|
||||
}));
|
||||
afterBuildTime = newFs.statSync(lastProjectOutputJs).mtimeMs;
|
||||
afterBuildTime = newFs.statSync(lastProjectOutput).mtimeMs;
|
||||
});
|
||||
after(() => {
|
||||
newFs = undefined!;
|
||||
@@ -358,6 +393,12 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
host.assertDiagnosticMessages(...(incrementalExpectedDiagnostics || emptyArray));
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Build should pass without errors if not verifying diagnostics
|
||||
it(`verify no errors`, () => {
|
||||
host.assertErrors(/*empty*/);
|
||||
});
|
||||
}
|
||||
it(`Generates files matching the baseline`, () => {
|
||||
generateBaseline(newFs, proj, scenario, subScenario, fs);
|
||||
});
|
||||
@@ -372,7 +413,6 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
|
||||
fs: newFs.shadow(),
|
||||
tick,
|
||||
rootNames,
|
||||
expectedMapFileNames: emptyArray,
|
||||
modifyFs: fs => {
|
||||
// Delete output files
|
||||
for (const outputFile of expectedOutputFiles) {
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace ts {
|
||||
tick,
|
||||
proj: "inferredTypeFromTransitiveModule",
|
||||
rootNames: ["/src"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: `/src/obj/index.js`,
|
||||
lastProjectOutput: `/src/obj/index.js`,
|
||||
outputFiles: [
|
||||
"/src/obj/bar.js", "/src/obj/bar.d.ts",
|
||||
"/src/obj/bundling.js", "/src/obj/bundling.d.ts",
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace ts {
|
||||
tick,
|
||||
proj: "lateBoundSymbol",
|
||||
rootNames: ["/src/tsconfig.json"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: "/src/src/main.js",
|
||||
lastProjectOutput: "/src/src/main.js",
|
||||
outputFiles: [
|
||||
"/src/src/hkt.js",
|
||||
"/src/src/main.js",
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
namespace ts {
|
||||
// https://github.com/microsoft/TypeScript/issues/31696
|
||||
it("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers to referenced projects resolve correctly", () => {
|
||||
const baseFs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, {
|
||||
files: {
|
||||
describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers to referenced projects resolve correctly", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
const { time, tick } = getTime();
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles({
|
||||
"/src/common/nominal.ts": utils.dedent`
|
||||
export declare type Nominal<T, Name extends string> = T & {
|
||||
[Symbol.species]: Name;
|
||||
@@ -71,7 +73,6 @@ namespace ts {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "lib",
|
||||
"lib": ["dom", "es2015", "es2015.symbol.wellknown"]
|
||||
}
|
||||
}`,
|
||||
"/tsconfig.json": utils.dedent`{
|
||||
@@ -83,16 +84,23 @@ namespace ts {
|
||||
],
|
||||
"include": []
|
||||
}`
|
||||
},
|
||||
cwd: "/"
|
||||
}, time, symbolLibContent);
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!;
|
||||
});
|
||||
verifyTsbuildOutput({
|
||||
scenario: `synthesized module specifiers resolve correctly`,
|
||||
projFs: () => projFs,
|
||||
time,
|
||||
tick,
|
||||
proj: "moduleSpecifiers",
|
||||
rootNames: ["/"],
|
||||
lastProjectOutput: `/src/lib/index.d.ts`,
|
||||
initialBuild: {
|
||||
modifyFs: noop,
|
||||
},
|
||||
baselineOnly: true
|
||||
});
|
||||
const fs = baseFs.makeReadonly().shadow();
|
||||
const sys = new fakes.System(fs, { executingFilePath: "/", newLine: "\n" });
|
||||
const host = new fakes.SolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(host, ["/tsconfig.json"], { dry: false, force: false, verbose: false });
|
||||
builder.build();
|
||||
|
||||
// Prior to fixing GH31696 the import in `/lib/src/sub-project-2/index.d.ts` was `import("../../lib/src/common/nonterminal")`, which was invalid.
|
||||
Harness.Baseline.runBaseline("tsbuild/moduleSpecifiers/initial-build/resolves-correctly.js", vfs.formatPatch(fs.diff(baseFs)));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace ts {
|
||||
rootNames: ["/src/third"],
|
||||
expectedMapFileNames,
|
||||
expectedBuildInfoFilesForSectionBaselines: expectedBuildInfoFilesForSectionBaselines || expectedTsbuildInfoFileNames,
|
||||
lastProjectOutputJs: outputFiles[project.third][ext.js],
|
||||
lastProjectOutput: outputFiles[project.third][ext.js],
|
||||
initialBuild: {
|
||||
modifyFs,
|
||||
expectedDiagnostics: initialExpectedDiagnostics,
|
||||
|
||||
@@ -617,7 +617,7 @@ export class cNew {}`);
|
||||
"/src/core/index.d.ts.map",
|
||||
"/src/logic/index.js.map"
|
||||
],
|
||||
lastProjectOutputJs: "/src/tests/index.js",
|
||||
lastProjectOutput: "/src/tests/index.js",
|
||||
initialBuild,
|
||||
incrementalDtsChangedBuild: {
|
||||
modifyFs: fs => appendText(fs, "/src/core/index.ts", `
|
||||
@@ -727,7 +727,7 @@ class someClass { }`),
|
||||
"/src/core/index.d.ts.map",
|
||||
"/src/logic/index.js.map"
|
||||
],
|
||||
lastProjectOutputJs: "/src/tests/index.js",
|
||||
lastProjectOutput: "/src/tests/index.js",
|
||||
initialBuild,
|
||||
incrementalDtsChangedBuild: {
|
||||
modifyFs: fs => replaceText(fs, "/src/logic/tsconfig.json", `"declaration": true,`, `"declaration": true,
|
||||
@@ -795,7 +795,7 @@ class someClass { }`),
|
||||
"/src/core/index.d.ts.map",
|
||||
"/src/logic/index.js.map"
|
||||
],
|
||||
lastProjectOutputJs: "/src/tests/index.js",
|
||||
lastProjectOutput: "/src/tests/index.js",
|
||||
initialBuild: {
|
||||
modifyFs: fs => replaceText(fs, "/src/logic/tsconfig.json", `"composite": true,`, `"composite": true,
|
||||
"tsBuildInfoFile": "ownFile.tsbuildinfo",`),
|
||||
@@ -851,8 +851,7 @@ class someClass { }`),
|
||||
tick,
|
||||
proj: "sample1",
|
||||
rootNames: ["/src/core"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: "/src/core/index.js",
|
||||
lastProjectOutput: "/src/core/index.js",
|
||||
initialBuild: {
|
||||
modifyFs: fs => fs.writeFileSync("/src/core/tsconfig.json", `{
|
||||
"compilerOptions": {
|
||||
@@ -892,8 +891,7 @@ class someClass { }`),
|
||||
tick,
|
||||
proj: "sample1",
|
||||
rootNames: ["/src/core"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: "/src/core/index.js",
|
||||
lastProjectOutput: "/src/core/index.js",
|
||||
initialBuild: {
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync("/lib/lib.esnext.full.d.ts", `/// <reference no-default-lib="true"/>
|
||||
@@ -942,8 +940,7 @@ class someClass { }`),
|
||||
tick,
|
||||
proj: "sample1",
|
||||
rootNames: ["/src/core"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: "/src/core/index.js",
|
||||
lastProjectOutput: "/src/core/index.js",
|
||||
initialBuild: {
|
||||
modifyFs: fs => fs.writeFileSync("/src/core/tsconfig.json", `{
|
||||
"compilerOptions": {
|
||||
@@ -981,8 +978,7 @@ class someClass { }`),
|
||||
tick,
|
||||
proj: "sample1",
|
||||
rootNames: ["/src/tests"],
|
||||
expectedMapFileNames: emptyArray,
|
||||
lastProjectOutputJs: "/src/tests/index.js",
|
||||
lastProjectOutput: "/src/tests/index.js",
|
||||
initialBuild: {
|
||||
modifyFs: fs => fs.writeFileSync("/src/tests/tsconfig.json", `{
|
||||
"references": [
|
||||
|
||||
@@ -16,17 +16,17 @@ namespace ts.tscWatch {
|
||||
expectedIncrementalEmit?: readonly File[];
|
||||
expectedIncrementalErrors?: readonly string[];
|
||||
}
|
||||
function verifyIncrementalWatchEmit(input: VerifyIncrementalWatchEmitInput) {
|
||||
function verifyIncrementalWatchEmit(input: () => VerifyIncrementalWatchEmitInput) {
|
||||
it("with tsc --w", () => {
|
||||
verifyIncrementalWatchEmitWorker({
|
||||
input,
|
||||
input: input(),
|
||||
emitAndReportErrors: createWatchOfConfigFile,
|
||||
verifyErrors: checkOutputErrorsInitial
|
||||
});
|
||||
});
|
||||
it("with tsc", () => {
|
||||
verifyIncrementalWatchEmitWorker({
|
||||
input,
|
||||
input: input(),
|
||||
emitAndReportErrors: incrementalBuild,
|
||||
verifyErrors: checkNormalBuildErrors
|
||||
});
|
||||
@@ -122,7 +122,7 @@ namespace ts.tscWatch {
|
||||
|
||||
function checkFileEmit(actual: Map<string>, expected: readonly File[]) {
|
||||
assert.equal(actual.size, expected.length, `Actual: ${JSON.stringify(arrayFrom(actual.entries()), /*replacer*/ undefined, " ")}\nExpected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}`);
|
||||
expected.forEach(file => {
|
||||
for (const file of expected) {
|
||||
let expectedContent = file.content;
|
||||
let actualContent = actual.get(file.path);
|
||||
if (isBuildInfoFile(file.path)) {
|
||||
@@ -130,7 +130,7 @@ namespace ts.tscWatch {
|
||||
expectedContent = sanitizeBuildInfo(expectedContent);
|
||||
}
|
||||
assert.equal(actualContent, expectedContent, `Emit for ${file.path}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const libFileInfo: BuilderState.FileInfo = {
|
||||
@@ -170,7 +170,7 @@ namespace ts.tscWatch {
|
||||
describe("own file emit without errors", () => {
|
||||
function verify(optionsToExtend?: CompilerOptions, expectedBuildinfoOptions?: CompilerOptions) {
|
||||
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, file2, configFile],
|
||||
optionsToExtend,
|
||||
expectedInitialEmit: [
|
||||
@@ -226,7 +226,7 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedIncrementalErrors: emptyArray,
|
||||
});
|
||||
}));
|
||||
}
|
||||
verify();
|
||||
describe("with commandline parameters that are not relative", () => {
|
||||
@@ -259,7 +259,7 @@ namespace ts.tscWatch {
|
||||
"file2.ts(1,7): error TS2322: Type '20' is not assignable to type 'string'.\n"
|
||||
];
|
||||
const modifiedFile1Content = file1.content.replace("x", "z");
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, fileModified, configFile],
|
||||
expectedInitialEmit: [
|
||||
file1Js,
|
||||
@@ -320,7 +320,7 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedIncrementalErrors: file2Errors,
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe("with --out", () => {
|
||||
@@ -332,7 +332,7 @@ namespace ts.tscWatch {
|
||||
path: `${project}/out.js`,
|
||||
content: "var x = 10;\nvar y = 20;\n"
|
||||
};
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, file2, config],
|
||||
expectedInitialEmit: [
|
||||
outFile,
|
||||
@@ -353,7 +353,7 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedInitialErrors: emptyArray
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
@@ -397,7 +397,7 @@ namespace ts.tscWatch {
|
||||
|
||||
describe("own file emit without errors", () => {
|
||||
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, file2, config],
|
||||
expectedInitialEmit: [
|
||||
file1Js,
|
||||
@@ -451,7 +451,7 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedIncrementalErrors: emptyArray,
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe("own file emit with errors", () => {
|
||||
@@ -479,7 +479,7 @@ namespace ts.tscWatch {
|
||||
"file2.ts(1,14): error TS2322: Type '20' is not assignable to type 'string'.\n"
|
||||
];
|
||||
const modifiedFile1Content = file1.content.replace("x = 10", "z = 10");
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, fileModified, config],
|
||||
expectedInitialEmit: [
|
||||
file1Js,
|
||||
@@ -541,6 +541,49 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedIncrementalErrors: file2Errors,
|
||||
}));
|
||||
|
||||
it("verify that state is read correctly", () => {
|
||||
const system = createWatchedSystem([libFile, file1, fileModified, config], { currentDirectory: project });
|
||||
incrementalBuild("tsconfig.json", system);
|
||||
|
||||
const command = parseConfigFileWithSystem("tsconfig.json", {}, system, noop)!;
|
||||
const builderProgram = createIncrementalProgram({
|
||||
rootNames: command.fileNames,
|
||||
options: command.options,
|
||||
projectReferences: command.projectReferences,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(command),
|
||||
host: createIncrementalCompilerHost(command.options, system)
|
||||
});
|
||||
|
||||
const state = builderProgram.getState();
|
||||
assert.equal(state.changedFilesSet!.size, 0, "changes");
|
||||
|
||||
assert.equal(state.fileInfos.size, 3, "FileInfo size");
|
||||
assert.deepEqual(state.fileInfos.get(libFile.path), libFileInfo);
|
||||
assert.deepEqual(state.fileInfos.get(file1.path), getFileInfo(file1.content));
|
||||
assert.deepEqual(state.fileInfos.get(file2.path), file2FileInfo);
|
||||
|
||||
assert.deepEqual(state.compilerOptions, {
|
||||
incremental: true,
|
||||
module: ModuleKind.AMD,
|
||||
configFilePath: config.path
|
||||
});
|
||||
|
||||
assert.equal(state.referencedMap!.size, 0);
|
||||
assert.equal(state.exportedModulesMap!.size, 0);
|
||||
|
||||
assert.equal(state.semanticDiagnosticsPerFile!.size, 3);
|
||||
assert.deepEqual(state.semanticDiagnosticsPerFile!.get(libFile.path), emptyArray);
|
||||
assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file1.path), emptyArray);
|
||||
const { file: _, relatedInformation: __, ...rest } = file2ReuasableError[1][0];
|
||||
assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file2.path), [{
|
||||
...rest,
|
||||
file: state.program!.getSourceFileByPath(file2.path as Path)!,
|
||||
relatedInformation: undefined,
|
||||
reportsUnnecessary: undefined,
|
||||
source: undefined
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -561,7 +604,7 @@ namespace ts.tscWatch {
|
||||
});
|
||||
`;
|
||||
}
|
||||
verifyIncrementalWatchEmit({
|
||||
verifyIncrementalWatchEmit(() => ({
|
||||
files: [libFile, file1, file2, config],
|
||||
expectedInitialEmit: [
|
||||
outFile,
|
||||
@@ -582,7 +625,140 @@ namespace ts.tscWatch {
|
||||
}
|
||||
],
|
||||
expectedInitialErrors: emptyArray
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe("incremental with circular references", () => {
|
||||
function getFileInfo(content: string): BuilderState.FileInfo {
|
||||
const signature = Harness.mockHash(content);
|
||||
return { version: signature, signature };
|
||||
}
|
||||
const config: File = {
|
||||
path: configFile.path,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
declaration: true,
|
||||
emitDeclarationOnly: true
|
||||
}
|
||||
})
|
||||
};
|
||||
const aTs: File = {
|
||||
path: `${project}/a.ts`,
|
||||
content: `import { B } from "./b";
|
||||
export interface A {
|
||||
b: B;
|
||||
}
|
||||
`
|
||||
};
|
||||
const bTs: File = {
|
||||
path: `${project}/b.ts`,
|
||||
content: `import { C } from "./c";
|
||||
export interface B {
|
||||
b: C;
|
||||
}
|
||||
`
|
||||
};
|
||||
const cTs: File = {
|
||||
path: `${project}/c.ts`,
|
||||
content: `import { A } from "./a";
|
||||
export interface C {
|
||||
a: A;
|
||||
}
|
||||
`
|
||||
};
|
||||
const indexTs: File = {
|
||||
path: `${project}/index.ts`,
|
||||
content: `export { A } from "./a";
|
||||
export { B } from "./b";
|
||||
export { C } from "./c";
|
||||
`
|
||||
};
|
||||
|
||||
verifyIncrementalWatchEmit(() => {
|
||||
const referencedMap: MapLike<string[]> = {
|
||||
"./a.ts": ["./b.ts"],
|
||||
"./b.ts": ["./c.ts"],
|
||||
"./c.ts": ["./a.ts"],
|
||||
"./index.ts": ["./a.ts", "./b.ts", "./c.ts"],
|
||||
};
|
||||
const initialProgram: ProgramBuildInfo = {
|
||||
fileInfos: {
|
||||
[libFilePath]: libFileInfo,
|
||||
"./c.ts": getFileInfo(cTs.content),
|
||||
"./b.ts": getFileInfo(bTs.content),
|
||||
"./a.ts": getFileInfo(aTs.content),
|
||||
"./index.ts": getFileInfo(indexTs.content)
|
||||
},
|
||||
options: {
|
||||
incremental: true,
|
||||
target: ScriptTarget.ES5,
|
||||
module: ModuleKind.CommonJS,
|
||||
declaration: true,
|
||||
emitDeclarationOnly: true,
|
||||
configFilePath: "./tsconfig.json"
|
||||
},
|
||||
referencedMap,
|
||||
exportedModulesMap: referencedMap,
|
||||
semanticDiagnosticsPerFile: [
|
||||
libFilePath,
|
||||
"./a.ts",
|
||||
"./b.ts",
|
||||
"./c.ts",
|
||||
"./index.ts",
|
||||
]
|
||||
};
|
||||
const { fileInfos, ...rest } = initialProgram;
|
||||
const expectedADts: File = { path: `${project}/a.d.ts`, content: aTs.content };
|
||||
const expectedBDts: File = { path: `${project}/b.d.ts`, content: bTs.content };
|
||||
const expectedCDts: File = { path: `${project}/c.d.ts`, content: cTs.content };
|
||||
const expectedIndexDts: File = { path: `${project}/index.d.ts`, content: indexTs.content };
|
||||
const modifiedATsContent = aTs.content.replace("b: B;", `b: B;
|
||||
foo: any;`);
|
||||
return {
|
||||
files: [libFile, aTs, bTs, cTs, indexTs, config],
|
||||
expectedInitialEmit: [
|
||||
expectedADts,
|
||||
expectedBDts,
|
||||
expectedCDts,
|
||||
expectedIndexDts,
|
||||
{
|
||||
path: `${project}/tsconfig.tsbuildinfo`,
|
||||
content: getBuildInfoText({
|
||||
program: initialProgram,
|
||||
version
|
||||
})
|
||||
}
|
||||
],
|
||||
expectedInitialErrors: emptyArray,
|
||||
modifyFs: host => host.writeFile(aTs.path, modifiedATsContent),
|
||||
expectedIncrementalEmit: [
|
||||
{ path: expectedADts.path, content: modifiedATsContent },
|
||||
expectedBDts,
|
||||
expectedCDts,
|
||||
expectedIndexDts,
|
||||
{
|
||||
path: `${project}/tsconfig.tsbuildinfo`,
|
||||
content: getBuildInfoText({
|
||||
program: {
|
||||
fileInfos: {
|
||||
[libFilePath]: libFileInfo,
|
||||
"./c.ts": getFileInfo(cTs.content),
|
||||
"./b.ts": getFileInfo(bTs.content),
|
||||
"./a.ts": getFileInfo(modifiedATsContent),
|
||||
"./index.ts": getFileInfo(indexTs.content)
|
||||
},
|
||||
...rest
|
||||
},
|
||||
version
|
||||
})
|
||||
}
|
||||
],
|
||||
expectedIncrementalErrors: emptyArray
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user