Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint

This commit is contained in:
Alexander
2019-08-31 22:12:41 +03:00
55 changed files with 1783 additions and 807 deletions

View File

@@ -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",

View File

@@ -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: [

View 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
});
});
}

View File

@@ -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) {

View File

@@ -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",

View File

@@ -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",

View File

@@ -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)));
});
}
}

View File

@@ -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,

View File

@@ -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": [

View File

@@ -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
};
});
});
});