Skip to content

Commit caf0041

Browse files
committed
Add listFilesOnly command-line option
Msbuild currently uses a combination of `--listFiles` and `--noEmit` to obtain a list of files to be consumed by tsc. However, these two flags don't suppress type checking, the results of which msbuild will never consume. This new switch gives msbuild a faster way to obtain the file list. Note: like `--noEmit`, doesn't make sense in build mode.
1 parent a8dc7af commit caf0041

File tree

13 files changed

+81
-19
lines changed

13 files changed

+81
-19
lines changed

src/compiler/checker.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -29651,7 +29651,7 @@ namespace ts {
2965129651

2965229652
function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
2965329653
// no rest parameters \ declaration context \ overload - no codegen impact
29654-
if (languageVersion >= ScriptTarget.ES2015 || compilerOptions.noEmit || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((<FunctionLikeDeclaration>node).body)) {
29654+
if (languageVersion >= ScriptTarget.ES2015 || shouldSuppressEmit(compilerOptions) || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((<FunctionLikeDeclaration>node).body)) {
2965529655
return;
2965629656
}
2965729657

@@ -29726,7 +29726,7 @@ namespace ts {
2972629726

2972729727
function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
2972829728
// No need to check for require or exports for ES6 modules and later
29729-
if (moduleKind >= ModuleKind.ES2015 || compilerOptions.noEmit) {
29729+
if (moduleKind >= ModuleKind.ES2015 || shouldSuppressEmit(compilerOptions)) {
2973029730
return;
2973129731
}
2973229732

@@ -29749,7 +29749,7 @@ namespace ts {
2974929749
}
2975029750

2975129751
function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void {
29752-
if (languageVersion >= ScriptTarget.ES2017 || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) {
29752+
if (languageVersion >= ScriptTarget.ES2017 || shouldSuppressEmit(compilerOptions) || !needCollisionCheckForIdentifier(node, name, "Promise")) {
2975329753
return;
2975429754
}
2975529755

@@ -35639,7 +35639,7 @@ namespace ts {
3563935639
return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation);
3564035640
}
3564135641

35642-
if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit &&
35642+
if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !shouldSuppressEmit(compilerOptions) &&
3564335643
!(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) {
3564435644
checkESModuleMarker(node.name);
3564535645
}

src/compiler/commandLineParser.ts

+7
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ namespace ts {
216216
isCommandLineOnly: true,
217217
description: Diagnostics.Print_the_final_configuration_instead_of_building
218218
},
219+
{
220+
name: "listFilesOnly",
221+
type: "boolean",
222+
category: Diagnostics.Command_line_Options,
223+
isCommandLineOnly: true,
224+
description: Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing
225+
},
219226

220227
// Basic
221228
{

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -4311,6 +4311,10 @@
43114311
"category": "Message",
43124312
"code": 6502
43134313
},
4314+
"Print names of files that are part of the compilation and then stop processing.": {
4315+
"category": "Message",
4316+
"code": 6503
4317+
},
43144318

43154319
"Variable '{0}' implicitly has an '{1}' type.": {
43164320
"category": "Error",

src/compiler/emitter.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ namespace ts {
332332
// Write build information if applicable
333333
if (!buildInfoPath || targetSourceFile || emitSkipped) return;
334334
const program = host.getProgramBuildInfo();
335-
if (host.isEmitBlocked(buildInfoPath) || compilerOptions.noEmit) {
335+
if (host.isEmitBlocked(buildInfoPath) || shouldSuppressEmit(compilerOptions)) {
336336
emitSkipped = true;
337337
return;
338338
}
@@ -349,7 +349,7 @@ namespace ts {
349349
}
350350

351351
// Make sure not to write js file and source map file if any of them cannot be written
352-
if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || compilerOptions.noEmit) {
352+
if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || shouldSuppressEmit(compilerOptions)) {
353353
emitSkipped = true;
354354
return;
355355
}
@@ -436,7 +436,7 @@ namespace ts {
436436
onEmitNode: declarationTransform.emitNodeWithNotification,
437437
substituteNode: declarationTransform.substituteNode,
438438
});
439-
const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit;
439+
const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!shouldSuppressEmit(compilerOptions);
440440
emitSkipped = emitSkipped || declBlocked;
441441
if (!declBlocked || forceDtsEmit) {
442442
Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform");

src/compiler/program.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,7 @@ namespace ts {
15601560
}
15611561

15621562
function getDiagnosticsProducingTypeChecker() {
1563+
Debug.assert(!options.listFilesOnly || !!options.extendedDiagnostics);
15631564
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
15641565
}
15651566

@@ -1582,11 +1583,11 @@ namespace ts {
15821583
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
15831584
let declarationDiagnostics: readonly Diagnostic[] = [];
15841585

1585-
if (!forceDtsEmit) {
1586-
if (options.noEmit) {
1587-
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
1588-
}
1586+
if (options.listFilesOnly || (!forceDtsEmit && shouldSuppressEmit(options))) {
1587+
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
1588+
}
15891589

1590+
if (!forceDtsEmit) {
15901591
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
15911592
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
15921593
// get any preEmit diagnostics, not just the ones
@@ -2036,7 +2037,9 @@ namespace ts {
20362037
}
20372038

20382039
function getGlobalDiagnostics(): SortedReadonlyArray<Diagnostic> {
2039-
return rootNames.length ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray<Diagnostic>;
2040+
return !options.listFilesOnly && rootNames.length
2041+
? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice())
2042+
: emptyArray as any as SortedReadonlyArray<Diagnostic>;
20402043
}
20412044

20422045
function getConfigFileParsingDiagnostics(): readonly Diagnostic[] {
@@ -3089,7 +3092,7 @@ namespace ts {
30893092
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite");
30903093
}
30913094

3092-
if (options.noEmit) {
3095+
if (shouldSuppressEmit(options)) {
30933096
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit");
30943097
}
30953098
}
@@ -3112,7 +3115,7 @@ namespace ts {
31123115
}
31133116

31143117
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
3115-
if (!options.noEmit && !options.suppressOutputPathCheck) {
3118+
if (!shouldSuppressEmit(options) && !options.suppressOutputPathCheck) {
31163119
const emitHost = getEmitHost();
31173120
const emitFilesSeen = createMap<true>();
31183121
forEachEmittedFile(emitHost, (emitFileNames) => {
@@ -3181,7 +3184,7 @@ namespace ts {
31813184
}
31823185

31833186
function verifyProjectReferences() {
3184-
const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined;
3187+
const buildInfoPath = !shouldSuppressEmit(options) && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined;
31853188
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
31863189
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
31873190
const parentFile = parent && parent.sourceFile as JsonSourceFile;
@@ -3322,7 +3325,7 @@ namespace ts {
33223325
}
33233326

33243327
function isEmittedFile(file: string): boolean {
3325-
if (options.noEmit) {
3328+
if (shouldSuppressEmit(options)) {
33263329
return false;
33273330
}
33283331

src/compiler/tsbuild.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ namespace ts {
167167
/*@internal*/ preserveWatchOutput?: boolean;
168168
/*@internal*/ listEmittedFiles?: boolean;
169169
/*@internal*/ listFiles?: boolean;
170+
/*@internal*/ listFilesOnly?: boolean;
170171
/*@internal*/ pretty?: boolean;
171172
incremental?: boolean;
172173

@@ -1923,7 +1924,7 @@ namespace ts {
19231924
}
19241925

19251926
function isOutputFile(state: SolutionBuilderState, fileName: string, configFile: ParsedCommandLine) {
1926-
if (configFile.options.noEmit) return false;
1927+
if (shouldSuppressEmit(configFile.options)) return false;
19271928

19281929
// ts or tsx files are not output
19291930
if (!fileExtensionIs(fileName, Extension.Dts) &&

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4951,6 +4951,7 @@ namespace ts {
49514951
lib?: string[];
49524952
/*@internal*/listEmittedFiles?: boolean;
49534953
/*@internal*/listFiles?: boolean;
4954+
/*@internal*/listFilesOnly?: boolean;
49544955
locale?: string;
49554956
mapRoot?: string;
49564957
maxNodeModuleJsDepth?: number;

src/compiler/utilities.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -7619,6 +7619,14 @@ namespace ts {
76197619
return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name];
76207620
}
76217621

7622+
export function shouldSuppressEmit(options: CompilerOptions): boolean {
7623+
return !!options.noEmit || !!options.listFilesOnly;
7624+
}
7625+
7626+
export function shouldListFiles(options: CompilerOptions): boolean {
7627+
return !!options.listFiles || !!options.listFilesOnly;
7628+
}
7629+
76227630
export function hasZeroOrOneAsteriskCharacter(str: string): boolean {
76237631
let seenAsterisk = false;
76247632
for (let i = 0; i < str.length; i++) {
@@ -8339,7 +8347,8 @@ namespace ts {
83398347
// If skipLibCheck is enabled, skip reporting errors if file is a declaration file.
83408348
// If skipDefaultLibCheck is enabled, skip reporting errors if file contains a
83418349
// '/// <reference no-default-lib="true"/>' directive.
8342-
return (options.skipLibCheck && sourceFile.isDeclarationFile ||
8350+
return options.listFilesOnly ||
8351+
(options.skipLibCheck && sourceFile.isDeclarationFile ||
83438352
options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) ||
83448353
host.isSourceOfProjectReferenceRedirect(sourceFile.fileName);
83458354
}

src/compiler/watch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ namespace ts {
129129
}
130130

131131
export function listFiles(program: ProgramToEmitFilesAndReportErrors, writeFileName: (s: string) => void) {
132-
if (program.getCompilerOptions().listFiles) {
132+
if (shouldListFiles(program.getCompilerOptions())) {
133133
forEach(program.getSourceFiles(), file => {
134134
writeFileName(file.fileName);
135135
});

src/testRunner/unittests/config/commandLineParsing.ts

+17
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,23 @@ namespace ts {
446446
});
447447
});
448448

449+
it("parse build with listFilesOnly ", () => {
450+
// --lib es6 0.ts
451+
assertParseResult(["--listFilesOnly"],
452+
{
453+
errors: [{
454+
messageText:"Unknown build option '--listFilesOnly'.",
455+
category: Diagnostics.Unknown_build_option_0.category,
456+
code: Diagnostics.Unknown_build_option_0.code,
457+
file: undefined,
458+
start: undefined,
459+
length: undefined,
460+
}],
461+
projects: ["."],
462+
buildOptions: {}
463+
});
464+
});
465+
449466
it("Parse multiple flags with input projects at the end", () => {
450467
// --lib es5,es2015.symbol.wellknown --target es5 0.ts
451468
assertParseResult(["--force", "--verbose", "src", "tests"],

src/tsc/executeCommandLine.ts

+5
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ namespace ts {
207207
return sys.exit(ExitStatus.Success);
208208
}
209209

210+
if (commandLine.options.watch && commandLine.options.listFilesOnly) {
211+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly"));
212+
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
213+
}
214+
210215
if (commandLine.options.project) {
211216
if (commandLine.fileNames.length !== 0) {
212217
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"listFilesOnly": true
4+
}
5+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @listFilesOnly: true
4+
5+
// @Filename: a.js
6+
////const x = 1;
7+
8+
// Just want to see that no baseline is emitted
9+
10+
verify.noErrors();

0 commit comments

Comments
 (0)