Skip to content

Commit b1d748b

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
2 parents b31d5b3 + 79bcb3d commit b1d748b

File tree

55 files changed

+1781
-805
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1781
-805
lines changed

src/compiler/builder.ts

+18-8
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ namespace ts {
137137
*/
138138
emittedBuildInfo?: boolean;
139139
/**
140-
* Already seen affected files
140+
* Already seen emitted files
141141
*/
142142
seenEmittedFiles: Map<true> | undefined;
143143
/**
@@ -329,7 +329,6 @@ namespace ts {
329329
handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, computeHash);
330330
return affectedFile;
331331
}
332-
seenAffectedFiles.set(affectedFile.path, true);
333332
affectedFilesIndex++;
334333
}
335334

@@ -549,7 +548,7 @@ namespace ts {
549548
* This is called after completing operation on the next affected file.
550549
* The operations here are postponed to ensure that cancellation during the iteration is handled correctly
551550
*/
552-
function doneWithAffectedFile(state: BuilderProgramState, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean) {
551+
function doneWithAffectedFile(state: BuilderProgramState, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean, isEmitResult?: boolean) {
553552
if (isBuildInfoEmit) {
554553
state.emittedBuildInfo = true;
555554
}
@@ -559,6 +558,9 @@ namespace ts {
559558
}
560559
else {
561560
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
561+
if (isEmitResult) {
562+
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, true);
563+
}
562564
if (isPendingEmit) {
563565
state.affectedFilesPendingEmitIndex!++;
564566
}
@@ -576,6 +578,14 @@ namespace ts {
576578
return { result, affected };
577579
}
578580

581+
/**
582+
* Returns the result with affected file
583+
*/
584+
function toAffectedFileEmitResult(state: BuilderProgramState, result: EmitResult, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean): AffectedFileResult<EmitResult> {
585+
doneWithAffectedFile(state, affected, isPendingEmit, isBuildInfoEmit, /*isEmitResult*/ true);
586+
return { result, affected };
587+
}
588+
579589
/**
580590
* Gets the semantic diagnostics either from cache if present, or otherwise from program and caches it
581591
* Note that it is assumed that the when asked about semantic diagnostics, the file has been taken out of affected files/changed file set
@@ -849,7 +859,7 @@ namespace ts {
849859
}
850860

851861
const affected = Debug.assertDefined(state.program);
852-
return toAffectedFileResult(
862+
return toAffectedFileEmitResult(
853863
state,
854864
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
855865
// Otherwise just affected file
@@ -872,14 +882,14 @@ namespace ts {
872882
}
873883
}
874884

875-
return toAffectedFileResult(
885+
return toAffectedFileEmitResult(
876886
state,
877887
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
878888
// Otherwise just affected file
879889
Debug.assertDefined(state.program).emit(affected === state.program ? undefined : affected as SourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers),
880890
affected,
881-
isPendingEmitFile
882-
);
891+
isPendingEmitFile,
892+
);
883893
}
884894

885895
/**
@@ -1036,7 +1046,7 @@ namespace ts {
10361046
compilerOptions: convertFromReusableCompilerOptions(program.options, toAbsolutePath),
10371047
referencedMap: getMapOfReferencedSet(program.referencedMap, toPath),
10381048
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap, toPath),
1039-
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => isString(value) ? value : value[0], value => isString(value) ? emptyArray : value[1]),
1049+
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toPath(isString(value) ? value : value[0]), value => isString(value) ? emptyArray : value[1]),
10401050
hasReusableDiagnostic: true
10411051
};
10421052
return {

src/compiler/builderState.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,13 @@ namespace ts.BuilderState {
345345
}
346346
else {
347347
const emitOutput = getFileEmitOutput(programOfThisState, sourceFile, /*emitOnlyDtsFiles*/ true, cancellationToken);
348-
if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) {
349-
latestSignature = computeHash(emitOutput.outputFiles[0].text);
348+
const firstDts = emitOutput.outputFiles &&
349+
programOfThisState.getCompilerOptions().declarationMap ?
350+
emitOutput.outputFiles.length > 1 ? emitOutput.outputFiles[1] : undefined :
351+
emitOutput.outputFiles.length > 0 ? emitOutput.outputFiles[0] : undefined;
352+
if (firstDts) {
353+
Debug.assert(fileExtensionIs(firstDts.name, Extension.Dts), "File extension for signature expected to be dts", () => `Found: ${getAnyExtensionFromPath(firstDts.name)} for ${firstDts.name}:: All output files: ${JSON.stringify(emitOutput.outputFiles.map(f => f.name))}`);
354+
latestSignature = computeHash(firstDts.text);
350355
if (exportedModulesMapCache && latestSignature !== prevSignature) {
351356
updateExportedModules(sourceFile, emitOutput.exportedModulesFromDeclarationEmit, exportedModulesMapCache);
352357
}

src/compiler/emitter.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ namespace ts {
155155
}
156156

157157
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
158+
if (configFile.options.emitDeclarationOnly) return undefined;
158159
const isJsonFile = fileExtensionIs(inputFileName, Extension.Json);
159160
const outputFileName = changeExtension(
160161
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.outDir),
@@ -187,7 +188,7 @@ namespace ts {
187188
const js = getOutputJSFileName(inputFileName, configFile, ignoreCase);
188189
addOutput(js);
189190
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
190-
if (configFile.options.sourceMap) {
191+
if (js && configFile.options.sourceMap) {
191192
addOutput(`${js}.map`);
192193
}
193194
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
@@ -214,6 +215,10 @@ namespace ts {
214215
if (fileExtensionIs(inputFileName, Extension.Dts)) continue;
215216
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase);
216217
if (jsFilePath) return jsFilePath;
218+
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
219+
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
220+
return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
221+
}
217222
}
218223
const buildInfoPath = getOutputPathForBuildInfo(configFile.options);
219224
if (buildInfoPath) return buildInfoPath;

src/harness/fakes.ts

+13
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,10 @@ ${indentText}${text}`;
545545
super.writeFile(fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
546546
}
547547

548+
createHash(data: string) {
549+
return `${ts.generateDjb2Hash(data)}-${data}`;
550+
}
551+
548552
now() {
549553
return new Date(this.sys.vfs.time());
550554
}
@@ -571,6 +575,15 @@ Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")}
571575
Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}`);
572576
}
573577

578+
assertErrors(...expectedDiagnostics: ExpectedErrorDiagnostic[]) {
579+
const actual = this.diagnostics.filter(d => d.kind === DiagnosticKind.Error).map(diagnosticToText);
580+
const expected = expectedDiagnostics.map(expectedDiagnosticToText);
581+
assert.deepEqual(actual, expected, `Diagnostics arrays did not match:
582+
Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")}
583+
Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}
584+
Actual All:: ${JSON.stringify(this.diagnostics.slice().map(diagnosticToText), /*replacer*/ undefined, " ")}`);
585+
}
586+
574587
printDiagnostics(header = "== Diagnostics ==") {
575588
const out = ts.createDiagnosticReporter(ts.sys);
576589
ts.sys.write(header + "\r\n");

src/services/formatting/smartIndenter.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,14 @@ namespace ts.formatting {
540540
return true;
541541
case SyntaxKind.VariableDeclaration:
542542
case SyntaxKind.PropertyAssignment:
543+
case SyntaxKind.BinaryExpression:
543544
if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217
544545
return rangeIsOnOneLine(sourceFile, child!);
545546
}
546-
return true;
547+
if (parent.kind !== SyntaxKind.BinaryExpression) {
548+
return true;
549+
}
550+
break;
547551
case SyntaxKind.DoStatement:
548552
case SyntaxKind.WhileStatement:
549553
case SyntaxKind.ForInStatement:

src/testRunner/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"unittests/tsbuild/amdModulesWithOut.ts",
9595
"unittests/tsbuild/containerOnlyReferenced.ts",
9696
"unittests/tsbuild/demo.ts",
97+
"unittests/tsbuild/emitDeclarationOnly.ts",
9798
"unittests/tsbuild/emptyFiles.ts",
9899
"unittests/tsbuild/graphOrdering.ts",
99100
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",

src/testRunner/unittests/tsbuild/amdModulesWithOut.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ namespace ts {
7777
[outputFiles[project.lib][ext.buildinfo], outputFiles[project.lib][ext.js], outputFiles[project.lib][ext.dts]],
7878
[outputFiles[project.app][ext.buildinfo], outputFiles[project.app][ext.js], outputFiles[project.app][ext.dts]]
7979
],
80-
lastProjectOutputJs: outputFiles[project.app][ext.js],
80+
lastProjectOutput: outputFiles[project.app][ext.js],
8181
initialBuild: {
8282
modifyFs
8383
},
@@ -231,7 +231,7 @@ ${internal} export enum internalEnum { a, b, c }`);
231231
[libOutputFile[ext.buildinfo], libOutputFile[ext.js], libOutputFile[ext.dts]],
232232
[outputFiles[project.app][ext.buildinfo], outputFiles[project.app][ext.js], outputFiles[project.app][ext.dts]]
233233
],
234-
lastProjectOutputJs: outputFiles[project.app][ext.js],
234+
lastProjectOutput: outputFiles[project.app][ext.js],
235235
initialBuild: {
236236
modifyFs,
237237
expectedDiagnostics: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
namespace ts {
2+
describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true", () => {
3+
let projFs: vfs.FileSystem;
4+
const { time, tick } = getTime();
5+
before(() => {
6+
projFs = loadProjectFromDisk("tests/projects/emitDeclarationOnly", time);
7+
});
8+
after(() => {
9+
projFs = undefined!;
10+
});
11+
12+
function verifyEmitDeclarationOnly(disableMap?: true) {
13+
verifyTsbuildOutput({
14+
scenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
15+
projFs: () => projFs,
16+
time,
17+
tick,
18+
proj: "emitDeclarationOnly",
19+
rootNames: ["/src"],
20+
lastProjectOutput: `/src/lib/index.d.ts`,
21+
outputFiles: [
22+
"/src/lib/a.d.ts",
23+
"/src/lib/b.d.ts",
24+
"/src/lib/c.d.ts",
25+
"/src/lib/index.d.ts",
26+
"/src/tsconfig.tsbuildinfo",
27+
...(disableMap ? emptyArray : [
28+
"/src/lib/a.d.ts.map",
29+
"/src/lib/b.d.ts.map",
30+
"/src/lib/c.d.ts.map",
31+
"/src/lib/index.d.ts.map"
32+
])
33+
],
34+
initialBuild: {
35+
modifyFs: disableMap ?
36+
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
37+
noop,
38+
expectedDiagnostics: [
39+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
40+
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
41+
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
42+
]
43+
},
44+
incrementalDtsChangedBuild: {
45+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
46+
expectedDiagnostics: [
47+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
48+
[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"],
49+
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
50+
]
51+
},
52+
baselineOnly: true,
53+
verifyDiagnostics: true
54+
});
55+
}
56+
verifyEmitDeclarationOnly();
57+
verifyEmitDeclarationOnly(/*disableMap*/ true);
58+
59+
verifyTsbuildOutput({
60+
scenario: `only dts output in non circular imports project with emitDeclarationOnly`,
61+
projFs: () => projFs,
62+
time,
63+
tick,
64+
proj: "emitDeclarationOnly",
65+
rootNames: ["/src"],
66+
lastProjectOutput: `/src/lib/a.d.ts`,
67+
outputFiles: [
68+
"/src/lib/a.d.ts",
69+
"/src/lib/b.d.ts",
70+
"/src/lib/c.d.ts",
71+
"/src/tsconfig.tsbuildinfo",
72+
"/src/lib/a.d.ts.map",
73+
"/src/lib/b.d.ts.map",
74+
"/src/lib/c.d.ts.map",
75+
],
76+
initialBuild: {
77+
modifyFs: fs => {
78+
fs.rimrafSync("/src/src/index.ts");
79+
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
80+
},
81+
expectedDiagnostics: [
82+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
83+
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
84+
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
85+
]
86+
},
87+
incrementalDtsChangedBuild: {
88+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
89+
expectedDiagnostics: [
90+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
91+
[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"],
92+
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
93+
]
94+
},
95+
incrementalDtsUnchangedBuild: {
96+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
97+
export interface A {`),
98+
expectedDiagnostics: [
99+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
100+
[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"],
101+
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
102+
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
103+
]
104+
},
105+
baselineOnly: true,
106+
verifyDiagnostics: true
107+
});
108+
});
109+
}

0 commit comments

Comments
 (0)