From caf0041f8a9b2eb11405e303533d805105b6a1d7 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 10 Oct 2019 16:54:11 -0700 Subject: [PATCH 1/6] 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. --- src/compiler/checker.ts | 8 +++---- src/compiler/commandLineParser.ts | 7 +++++++ src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/emitter.ts | 6 +++--- src/compiler/program.ts | 21 +++++++++++-------- src/compiler/tsbuild.ts | 3 ++- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 11 +++++++++- src/compiler/watch.ts | 2 +- .../unittests/config/commandLineParsing.ts | 17 +++++++++++++++ src/tsc/executeCommandLine.ts | 5 +++++ .../listFilesOnly/tsconfig.json | 5 +++++ tests/cases/fourslash/listFilesOnly.ts | 10 +++++++++ 13 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/listFilesOnly/tsconfig.json create mode 100644 tests/cases/fourslash/listFilesOnly.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b689cbf26f..7cab43a6931 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29651,7 +29651,7 @@ namespace ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (languageVersion >= ScriptTarget.ES2015 || compilerOptions.noEmit || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node).body)) { + if (languageVersion >= ScriptTarget.ES2015 || shouldSuppressEmit(compilerOptions) || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node).body)) { return; } @@ -29726,7 +29726,7 @@ namespace ts { function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { // No need to check for require or exports for ES6 modules and later - if (moduleKind >= ModuleKind.ES2015 || compilerOptions.noEmit) { + if (moduleKind >= ModuleKind.ES2015 || shouldSuppressEmit(compilerOptions)) { return; } @@ -29749,7 +29749,7 @@ namespace ts { } function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void { - if (languageVersion >= ScriptTarget.ES2017 || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { + if (languageVersion >= ScriptTarget.ES2017 || shouldSuppressEmit(compilerOptions) || !needCollisionCheckForIdentifier(node, name, "Promise")) { return; } @@ -35639,7 +35639,7 @@ namespace ts { return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation); } - if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit && + if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !shouldSuppressEmit(compilerOptions) && !(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) { checkESModuleMarker(node.name); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 18280ecefdb..57278bd7be4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -216,6 +216,13 @@ namespace ts { isCommandLineOnly: true, description: Diagnostics.Print_the_final_configuration_instead_of_building }, + { + name: "listFilesOnly", + type: "boolean", + category: Diagnostics.Command_line_Options, + isCommandLineOnly: true, + description: Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing + }, // Basic { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 100d1a55a0b..5cb18c1f333 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4311,6 +4311,10 @@ "category": "Message", "code": 6502 }, + "Print names of files that are part of the compilation and then stop processing.": { + "category": "Message", + "code": 6503 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cbff1fb2512..636d7c333f7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -332,7 +332,7 @@ namespace ts { // Write build information if applicable if (!buildInfoPath || targetSourceFile || emitSkipped) return; const program = host.getProgramBuildInfo(); - if (host.isEmitBlocked(buildInfoPath) || compilerOptions.noEmit) { + if (host.isEmitBlocked(buildInfoPath) || shouldSuppressEmit(compilerOptions)) { emitSkipped = true; return; } @@ -349,7 +349,7 @@ namespace ts { } // Make sure not to write js file and source map file if any of them cannot be written - if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || compilerOptions.noEmit) { + if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || shouldSuppressEmit(compilerOptions)) { emitSkipped = true; return; } @@ -436,7 +436,7 @@ namespace ts { onEmitNode: declarationTransform.emitNodeWithNotification, substituteNode: declarationTransform.substituteNode, }); - const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; + const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!shouldSuppressEmit(compilerOptions); emitSkipped = emitSkipped || declBlocked; if (!declBlocked || forceDtsEmit) { Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0c8444daa2f..df652da3f6a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1560,6 +1560,7 @@ namespace ts { } function getDiagnosticsProducingTypeChecker() { + Debug.assert(!options.listFilesOnly || !!options.extendedDiagnostics); return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true)); } @@ -1582,11 +1583,11 @@ namespace ts { function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { let declarationDiagnostics: readonly Diagnostic[] = []; - if (!forceDtsEmit) { - if (options.noEmit) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; - } + if (options.listFilesOnly || (!forceDtsEmit && shouldSuppressEmit(options))) { + return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + } + if (!forceDtsEmit) { // If the noEmitOnError flag is set, then check if we have any errors so far. If so, // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we // get any preEmit diagnostics, not just the ones @@ -2036,7 +2037,9 @@ namespace ts { } function getGlobalDiagnostics(): SortedReadonlyArray { - return rootNames.length ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray; + return !options.listFilesOnly && rootNames.length + ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) + : emptyArray as any as SortedReadonlyArray; } function getConfigFileParsingDiagnostics(): readonly Diagnostic[] { @@ -3089,7 +3092,7 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); } - if (options.noEmit) { + if (shouldSuppressEmit(options)) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); } } @@ -3112,7 +3115,7 @@ namespace ts { } // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files - if (!options.noEmit && !options.suppressOutputPathCheck) { + if (!shouldSuppressEmit(options) && !options.suppressOutputPathCheck) { const emitHost = getEmitHost(); const emitFilesSeen = createMap(); forEachEmittedFile(emitHost, (emitFileNames) => { @@ -3181,7 +3184,7 @@ namespace ts { } function verifyProjectReferences() { - const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; + const buildInfoPath = !shouldSuppressEmit(options) && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => { const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index]; const parentFile = parent && parent.sourceFile as JsonSourceFile; @@ -3322,7 +3325,7 @@ namespace ts { } function isEmittedFile(file: string): boolean { - if (options.noEmit) { + if (shouldSuppressEmit(options)) { return false; } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 1924be4df89..dd590e357a4 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -167,6 +167,7 @@ namespace ts { /*@internal*/ preserveWatchOutput?: boolean; /*@internal*/ listEmittedFiles?: boolean; /*@internal*/ listFiles?: boolean; + /*@internal*/ listFilesOnly?: boolean; /*@internal*/ pretty?: boolean; incremental?: boolean; @@ -1923,7 +1924,7 @@ namespace ts { } function isOutputFile(state: SolutionBuilderState, fileName: string, configFile: ParsedCommandLine) { - if (configFile.options.noEmit) return false; + if (shouldSuppressEmit(configFile.options)) return false; // ts or tsx files are not output if (!fileExtensionIs(fileName, Extension.Dts) && diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 03b849b36c7..f8f03dff446 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4951,6 +4951,7 @@ namespace ts { lib?: string[]; /*@internal*/listEmittedFiles?: boolean; /*@internal*/listFiles?: boolean; + /*@internal*/listFilesOnly?: boolean; locale?: string; mapRoot?: string; maxNodeModuleJsDepth?: number; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a841007d9d5..4d14b6b7e0c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7619,6 +7619,14 @@ namespace ts { return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name]; } + export function shouldSuppressEmit(options: CompilerOptions): boolean { + return !!options.noEmit || !!options.listFilesOnly; + } + + export function shouldListFiles(options: CompilerOptions): boolean { + return !!options.listFiles || !!options.listFilesOnly; + } + export function hasZeroOrOneAsteriskCharacter(str: string): boolean { let seenAsterisk = false; for (let i = 0; i < str.length; i++) { @@ -8339,7 +8347,8 @@ namespace ts { // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a // '/// ' directive. - return (options.skipLibCheck && sourceFile.isDeclarationFile || + return options.listFilesOnly || + (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) || host.isSourceOfProjectReferenceRedirect(sourceFile.fileName); } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index cac3f3009b1..acbf4ff162a 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -129,7 +129,7 @@ namespace ts { } export function listFiles(program: ProgramToEmitFilesAndReportErrors, writeFileName: (s: string) => void) { - if (program.getCompilerOptions().listFiles) { + if (shouldListFiles(program.getCompilerOptions())) { forEach(program.getSourceFiles(), file => { writeFileName(file.fileName); }); diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index 5c4998a750a..5792ee1a39c 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -446,6 +446,23 @@ namespace ts { }); }); + it("parse build with listFilesOnly ", () => { + // --lib es6 0.ts + assertParseResult(["--listFilesOnly"], + { + errors: [{ + messageText:"Unknown build option '--listFilesOnly'.", + category: Diagnostics.Unknown_build_option_0.category, + code: Diagnostics.Unknown_build_option_0.code, + file: undefined, + start: undefined, + length: undefined, + }], + projects: ["."], + buildOptions: {} + }); + }); + it("Parse multiple flags with input projects at the end", () => { // --lib es5,es2015.symbol.wellknown --target es5 0.ts assertParseResult(["--force", "--verbose", "src", "tests"], diff --git a/src/tsc/executeCommandLine.ts b/src/tsc/executeCommandLine.ts index cf813fa2f60..d730de4a981 100644 --- a/src/tsc/executeCommandLine.ts +++ b/src/tsc/executeCommandLine.ts @@ -207,6 +207,11 @@ namespace ts { return sys.exit(ExitStatus.Success); } + if (commandLine.options.watch && commandLine.options.listFilesOnly) { + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly")); + return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + if (commandLine.options.project) { if (commandLine.fileNames.length !== 0) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/listFilesOnly/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/listFilesOnly/tsconfig.json new file mode 100644 index 00000000000..9134bd8c6fa --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/listFilesOnly/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "listFilesOnly": true + } +} diff --git a/tests/cases/fourslash/listFilesOnly.ts b/tests/cases/fourslash/listFilesOnly.ts new file mode 100644 index 00000000000..63e2ba19407 --- /dev/null +++ b/tests/cases/fourslash/listFilesOnly.ts @@ -0,0 +1,10 @@ +/// + +// @listFilesOnly: true + +// @Filename: a.js +////const x = 1; + +// Just want to see that no baseline is emitted + +verify.noErrors(); \ No newline at end of file From d18130d36b9bbda5a988a02e048dccafffe98f40 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 16 Oct 2019 14:09:57 -0700 Subject: [PATCH 2/6] Consolidate checks in emitFilesAndReportErrors --- src/compiler/checker.ts | 8 ++++---- src/compiler/emitter.ts | 6 +++--- src/compiler/program.ts | 20 +++++++++----------- src/compiler/tsbuild.ts | 3 +-- src/compiler/utilities.ts | 11 +---------- src/compiler/watch.ts | 17 ++++++++++++----- 6 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7cab43a6931..1b689cbf26f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29651,7 +29651,7 @@ namespace ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (languageVersion >= ScriptTarget.ES2015 || shouldSuppressEmit(compilerOptions) || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node).body)) { + if (languageVersion >= ScriptTarget.ES2015 || compilerOptions.noEmit || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node).body)) { return; } @@ -29726,7 +29726,7 @@ namespace ts { function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { // No need to check for require or exports for ES6 modules and later - if (moduleKind >= ModuleKind.ES2015 || shouldSuppressEmit(compilerOptions)) { + if (moduleKind >= ModuleKind.ES2015 || compilerOptions.noEmit) { return; } @@ -29749,7 +29749,7 @@ namespace ts { } function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void { - if (languageVersion >= ScriptTarget.ES2017 || shouldSuppressEmit(compilerOptions) || !needCollisionCheckForIdentifier(node, name, "Promise")) { + if (languageVersion >= ScriptTarget.ES2017 || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { return; } @@ -35639,7 +35639,7 @@ namespace ts { return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation); } - if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !shouldSuppressEmit(compilerOptions) && + if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit && !(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) { checkESModuleMarker(node.name); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 636d7c333f7..cbff1fb2512 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -332,7 +332,7 @@ namespace ts { // Write build information if applicable if (!buildInfoPath || targetSourceFile || emitSkipped) return; const program = host.getProgramBuildInfo(); - if (host.isEmitBlocked(buildInfoPath) || shouldSuppressEmit(compilerOptions)) { + if (host.isEmitBlocked(buildInfoPath) || compilerOptions.noEmit) { emitSkipped = true; return; } @@ -349,7 +349,7 @@ namespace ts { } // Make sure not to write js file and source map file if any of them cannot be written - if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || shouldSuppressEmit(compilerOptions)) { + if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || compilerOptions.noEmit) { emitSkipped = true; return; } @@ -436,7 +436,7 @@ namespace ts { onEmitNode: declarationTransform.emitNodeWithNotification, substituteNode: declarationTransform.substituteNode, }); - const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!shouldSuppressEmit(compilerOptions); + const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || forceDtsEmit) { Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index df652da3f6a..883b793bd42 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1583,11 +1583,11 @@ namespace ts { function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { let declarationDiagnostics: readonly Diagnostic[] = []; - if (options.listFilesOnly || (!forceDtsEmit && shouldSuppressEmit(options))) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; - } - if (!forceDtsEmit) { + if (options.noEmit) { + return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + } + // If the noEmitOnError flag is set, then check if we have any errors so far. If so, // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we // get any preEmit diagnostics, not just the ones @@ -2037,9 +2037,7 @@ namespace ts { } function getGlobalDiagnostics(): SortedReadonlyArray { - return !options.listFilesOnly && rootNames.length - ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) - : emptyArray as any as SortedReadonlyArray; + return rootNames.length ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray; } function getConfigFileParsingDiagnostics(): readonly Diagnostic[] { @@ -3092,7 +3090,7 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); } - if (shouldSuppressEmit(options)) { + if (options.noEmit) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); } } @@ -3115,7 +3113,7 @@ namespace ts { } // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files - if (!shouldSuppressEmit(options) && !options.suppressOutputPathCheck) { + if (!options.noEmit && !options.suppressOutputPathCheck) { const emitHost = getEmitHost(); const emitFilesSeen = createMap(); forEachEmittedFile(emitHost, (emitFileNames) => { @@ -3184,7 +3182,7 @@ namespace ts { } function verifyProjectReferences() { - const buildInfoPath = !shouldSuppressEmit(options) && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; + const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => { const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index]; const parentFile = parent && parent.sourceFile as JsonSourceFile; @@ -3325,7 +3323,7 @@ namespace ts { } function isEmittedFile(file: string): boolean { - if (shouldSuppressEmit(options)) { + if (options.noEmit) { return false; } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index dd590e357a4..1924be4df89 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -167,7 +167,6 @@ namespace ts { /*@internal*/ preserveWatchOutput?: boolean; /*@internal*/ listEmittedFiles?: boolean; /*@internal*/ listFiles?: boolean; - /*@internal*/ listFilesOnly?: boolean; /*@internal*/ pretty?: boolean; incremental?: boolean; @@ -1924,7 +1923,7 @@ namespace ts { } function isOutputFile(state: SolutionBuilderState, fileName: string, configFile: ParsedCommandLine) { - if (shouldSuppressEmit(configFile.options)) return false; + if (configFile.options.noEmit) return false; // ts or tsx files are not output if (!fileExtensionIs(fileName, Extension.Dts) && diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4d14b6b7e0c..a841007d9d5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7619,14 +7619,6 @@ namespace ts { return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name]; } - export function shouldSuppressEmit(options: CompilerOptions): boolean { - return !!options.noEmit || !!options.listFilesOnly; - } - - export function shouldListFiles(options: CompilerOptions): boolean { - return !!options.listFiles || !!options.listFilesOnly; - } - export function hasZeroOrOneAsteriskCharacter(str: string): boolean { let seenAsterisk = false; for (let i = 0; i < str.length; i++) { @@ -8347,8 +8339,7 @@ namespace ts { // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a // '/// ' directive. - return options.listFilesOnly || - (options.skipLibCheck && sourceFile.isDeclarationFile || + return (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) || host.isSourceOfProjectReferenceRedirect(sourceFile.fileName); } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index acbf4ff162a..63b194c2077 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -129,7 +129,7 @@ namespace ts { } export function listFiles(program: ProgramToEmitFilesAndReportErrors, writeFileName: (s: string) => void) { - if (shouldListFiles(program.getCompilerOptions())) { + if (program.getCompilerOptions().listFiles || program.getCompilerOptions().listFilesOnly) { forEach(program.getSourceFiles(), file => { writeFileName(file.fileName); }); @@ -149,6 +149,8 @@ namespace ts { emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers ) { + const isListFilesOnly = !!program.getCompilerOptions().listFilesOnly; + // First get and report any syntactic errors. const diagnostics = program.getConfigFileParsingDiagnostics().slice(); const configFileParsingDiagnosticsLength = diagnostics.length; @@ -158,15 +160,20 @@ namespace ts { // semantic errors. if (diagnostics.length === configFileParsingDiagnosticsLength) { addRange(diagnostics, program.getOptionsDiagnostics(cancellationToken)); - addRange(diagnostics, program.getGlobalDiagnostics(cancellationToken)); - if (diagnostics.length === configFileParsingDiagnosticsLength) { - addRange(diagnostics, program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken)); + if (!isListFilesOnly) { + addRange(diagnostics, program.getGlobalDiagnostics(cancellationToken)); + + if (diagnostics.length === configFileParsingDiagnosticsLength) { + addRange(diagnostics, program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken)); + } } } // Emit and report any errors we ran into. - const emitResult = program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); + const emitResult = isListFilesOnly + ? { emitSkipped: true, diagnostics: emptyArray } + : program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); const { emittedFiles, diagnostics: emitDiagnostics } = emitResult; addRange(diagnostics, emitDiagnostics); From 9dd83912447fa4923c14c3542a6a472ac3a2fbaa Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 17 Oct 2019 16:32:48 -0700 Subject: [PATCH 3/6] Add additional properties to switch declaration --- src/compiler/commandLineParser.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 57278bd7be4..c9517440ac6 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -220,6 +220,8 @@ namespace ts { name: "listFilesOnly", type: "boolean", category: Diagnostics.Command_line_Options, + affectsSemanticDiagnostics: true, + affectsEmit: true, isCommandLineOnly: true, description: Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing }, From 8927aaabb5722addfc4c7a78a6b7e9009663506a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 17 Oct 2019 16:50:22 -0700 Subject: [PATCH 4/6] Rewrite tests --- src/testRunner/tsconfig.json | 1 + src/testRunner/unittests/tsc/listFilesOnly.ts | 33 +++++++++++++++++++ .../initial-build/after-watch.js | 6 ++++ .../initial-build/before-watch.js | 6 ++++ .../listFilesOnly/initial-build/loose-file.js | 7 ++++ tests/cases/fourslash/listFilesOnly.ts | 10 ------ 6 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 src/testRunner/unittests/tsc/listFilesOnly.ts create mode 100644 tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js create mode 100644 tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js create mode 100644 tests/baselines/reference/tsc/listFilesOnly/initial-build/loose-file.js delete mode 100644 tests/cases/fourslash/listFilesOnly.ts diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 15beae61f25..6c120e30349 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -116,6 +116,7 @@ "unittests/tsbuild/watchMode.ts", "unittests/tsc/declarationEmit.ts", "unittests/tsc/incremental.ts", + "unittests/tsc/listFilesOnly.ts", "unittests/tscWatch/consoleClearing.ts", "unittests/tscWatch/emit.ts", "unittests/tscWatch/emitAndErrorUpdates.ts", diff --git a/src/testRunner/unittests/tsc/listFilesOnly.ts b/src/testRunner/unittests/tsc/listFilesOnly.ts new file mode 100644 index 00000000000..07b3b25c467 --- /dev/null +++ b/src/testRunner/unittests/tsc/listFilesOnly.ts @@ -0,0 +1,33 @@ +namespace ts { + describe("unittests:: tsc:: listFilesOnly::", () => { + verifyTsc({ + scenario: "listFilesOnly", + subScenario: "before watch", + fs: () => loadProjectFromFiles({ + "/src/test.ts": utils.dedent` + export const x = 1;`, + }), + commandLineArgs: ["/src/test.ts", "--listFilesOnly", "--watch"] + }); + + verifyTsc({ + scenario: "listFilesOnly", + subScenario: "after watch", + fs: () => loadProjectFromFiles({ + "/src/test.ts": utils.dedent` + export const x = 1;`, + }), + commandLineArgs: ["/src/test.ts", "--watch", "--listFilesOnly"] + }); + + verifyTsc({ + scenario: "listFilesOnly", + subScenario: "loose file", + fs: () => loadProjectFromFiles({ + "/src/test.ts": utils.dedent` + export const x = 1;`, + }), + commandLineArgs: ["/src/test.ts", "--listFilesOnly"] + }); + }); +} diff --git a/tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js b/tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js new file mode 100644 index 00000000000..7ef3574626b --- /dev/null +++ b/tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js @@ -0,0 +1,6 @@ +//// [/lib/initial-buildOutput.txt] +/lib/tsc /src/test.ts --watch --listFilesOnly +error TS6370: Options 'watch' and 'listFilesOnly' cannot be combined. +exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped + + diff --git a/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js b/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js new file mode 100644 index 00000000000..c88653ae43b --- /dev/null +++ b/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js @@ -0,0 +1,6 @@ +//// [/lib/initial-buildOutput.txt] +/lib/tsc /src/test.ts --listFilesOnly --watch +error TS6370: Options 'watch' and 'listFilesOnly' cannot be combined. +exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped + + diff --git a/tests/baselines/reference/tsc/listFilesOnly/initial-build/loose-file.js b/tests/baselines/reference/tsc/listFilesOnly/initial-build/loose-file.js new file mode 100644 index 00000000000..6a97401e560 --- /dev/null +++ b/tests/baselines/reference/tsc/listFilesOnly/initial-build/loose-file.js @@ -0,0 +1,7 @@ +//// [/lib/initial-buildOutput.txt] +/lib/tsc /src/test.ts --listFilesOnly +/lib/lib.d.ts +/src/test.ts +exitCode:: ExitStatus.Success + + diff --git a/tests/cases/fourslash/listFilesOnly.ts b/tests/cases/fourslash/listFilesOnly.ts deleted file mode 100644 index 63e2ba19407..00000000000 --- a/tests/cases/fourslash/listFilesOnly.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -// @listFilesOnly: true - -// @Filename: a.js -////const x = 1; - -// Just want to see that no baseline is emitted - -verify.noErrors(); \ No newline at end of file From 526e413abcf1b827629d69e9997dd99aac83ed7f Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 17 Oct 2019 16:51:30 -0700 Subject: [PATCH 5/6] Dropping assert for 3.7 --- src/compiler/program.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 883b793bd42..0c8444daa2f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1560,7 +1560,6 @@ namespace ts { } function getDiagnosticsProducingTypeChecker() { - Debug.assert(!options.listFilesOnly || !!options.extendedDiagnostics); return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true)); } From 7275e9ca93e634cb0e2d8e7f57bd3c00c72d9d93 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 17 Oct 2019 17:22:47 -0700 Subject: [PATCH 6/6] Delete redundant test --- src/testRunner/unittests/tsc/listFilesOnly.ts | 12 +----------- .../tsc/listFilesOnly/initial-build/before-watch.js | 6 ------ .../{after-watch.js => combined-with-watch.js} | 0 3 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js rename tests/baselines/reference/tsc/listFilesOnly/initial-build/{after-watch.js => combined-with-watch.js} (100%) diff --git a/src/testRunner/unittests/tsc/listFilesOnly.ts b/src/testRunner/unittests/tsc/listFilesOnly.ts index 07b3b25c467..5655d3d7614 100644 --- a/src/testRunner/unittests/tsc/listFilesOnly.ts +++ b/src/testRunner/unittests/tsc/listFilesOnly.ts @@ -2,17 +2,7 @@ namespace ts { describe("unittests:: tsc:: listFilesOnly::", () => { verifyTsc({ scenario: "listFilesOnly", - subScenario: "before watch", - fs: () => loadProjectFromFiles({ - "/src/test.ts": utils.dedent` - export const x = 1;`, - }), - commandLineArgs: ["/src/test.ts", "--listFilesOnly", "--watch"] - }); - - verifyTsc({ - scenario: "listFilesOnly", - subScenario: "after watch", + subScenario: "combined with watch", fs: () => loadProjectFromFiles({ "/src/test.ts": utils.dedent` export const x = 1;`, diff --git a/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js b/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js deleted file mode 100644 index c88653ae43b..00000000000 --- a/tests/baselines/reference/tsc/listFilesOnly/initial-build/before-watch.js +++ /dev/null @@ -1,6 +0,0 @@ -//// [/lib/initial-buildOutput.txt] -/lib/tsc /src/test.ts --listFilesOnly --watch -error TS6370: Options 'watch' and 'listFilesOnly' cannot be combined. -exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped - - diff --git a/tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js b/tests/baselines/reference/tsc/listFilesOnly/initial-build/combined-with-watch.js similarity index 100% rename from tests/baselines/reference/tsc/listFilesOnly/initial-build/after-watch.js rename to tests/baselines/reference/tsc/listFilesOnly/initial-build/combined-with-watch.js