From 8fd6ddfcc65cda5cad9c1ca3a58517e4f55b5ca8 Mon Sep 17 00:00:00 2001 From: Ryan Myrvold <2127198+RyanMyrvold@users.noreply.github.com> Date: Sat, 23 Nov 2024 10:02:23 -0500 Subject: [PATCH 1/2] feat: baseline improvements and project diagnostics setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensured tsc builds successfully with current configurations. Added foundational tests for files: [] and composite edge cases. Verified behavior for ambiguous container projects, such as tsconfig.json with no actionable task. Confirmed alignment with TypeScript’s existing design goals, including: Non-breaking changes. No impact on JavaScript output or runtime behavior. --- src/compiler/commandLineParser.ts | 41 +++++++++++++++- src/compiler/diagnosticMessages.json | 4 ++ src/compiler/program.ts | 39 ++++++++++++++- tests/baselines/reference/api/typescript.d.ts | 16 ++++++ .../reference/containerProjectNoEmit.js | 15 ++++++ .../reference/containerProjectNoEmit.symbols | 10 ++++ .../reference/containerProjectNoEmit.types | 16 ++++++ ...itToDeclarationDirWithDeclarationOption.js | 17 +++++++ tests/baselines/reference/emptyFilesConfig.js | 14 ++++++ .../reference/emptyFilesConfig.symbols | 9 ++++ .../reference/emptyFilesConfig.types | 15 ++++++ .../reference/filesWithReferences.js | 17 +++++++ .../reference/filesWithReferences.symbols | 14 ++++++ .../reference/filesWithReferences.types | 28 +++++++++++ .../nodeAllowJsPackageSelfName2.errors.txt | 49 +++++++++++++++++++ .../reference/nodeAllowJsPackageSelfName2.js | 12 +++-- .../nodeAllowJsPackageSelfName2.types | 4 +- .../baselines/reference/solutionStyleRoot.js | 21 ++++++++ .../reference/solutionStyleRoot.symbols | 18 +++++++ .../reference/solutionStyleRoot.types | 34 +++++++++++++ ...ndle-@types-if-input-file-list-is-empty.js | 2 + ...e-tolerated-without-crashing-the-server.js | 2 + .../reference/validCompositeProject.js | 16 ++++++ .../reference/validCompositeProject.symbols | 13 +++++ .../reference/validCompositeProject.types | 22 +++++++++ .../cases/compiler/containerProjectNoEmit.ts | 3 ++ ...itToDeclarationDirWithDeclarationOption.ts | 7 ++- tests/cases/compiler/emptyFilesConfig.ts | 3 ++ tests/cases/compiler/filesWithReferences.ts | 4 ++ tests/cases/compiler/solutionStyleRoot.ts | 6 +++ tests/cases/compiler/validCompositeProject.ts | 5 ++ .../allowJs/nodeAllowJsPackageSelfName2.ts | 15 ++++-- 32 files changed, 475 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/containerProjectNoEmit.js create mode 100644 tests/baselines/reference/containerProjectNoEmit.symbols create mode 100644 tests/baselines/reference/containerProjectNoEmit.types create mode 100644 tests/baselines/reference/emptyFilesConfig.js create mode 100644 tests/baselines/reference/emptyFilesConfig.symbols create mode 100644 tests/baselines/reference/emptyFilesConfig.types create mode 100644 tests/baselines/reference/filesWithReferences.js create mode 100644 tests/baselines/reference/filesWithReferences.symbols create mode 100644 tests/baselines/reference/filesWithReferences.types create mode 100644 tests/baselines/reference/nodeAllowJsPackageSelfName2.errors.txt create mode 100644 tests/baselines/reference/solutionStyleRoot.js create mode 100644 tests/baselines/reference/solutionStyleRoot.symbols create mode 100644 tests/baselines/reference/solutionStyleRoot.types create mode 100644 tests/baselines/reference/validCompositeProject.js create mode 100644 tests/baselines/reference/validCompositeProject.symbols create mode 100644 tests/baselines/reference/validCompositeProject.types create mode 100644 tests/cases/compiler/containerProjectNoEmit.ts create mode 100644 tests/cases/compiler/emptyFilesConfig.ts create mode 100644 tests/cases/compiler/filesWithReferences.ts create mode 100644 tests/cases/compiler/solutionStyleRoot.ts create mode 100644 tests/cases/compiler/validCompositeProject.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 113d2107f247d..b223427496498 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2949,8 +2949,45 @@ function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undef * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ -export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine { - return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache); +export function parseJsonConfigFileContent( + json: any, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, +): ParsedCommandLine { + const parsed = parseJsonConfigFileContentWorker( + json, + /*sourceFile*/ undefined, + host, + basePath, + existingOptions, + existingWatchOptions, + configFileName, + resolutionStack, + extraFileExtensions, + extendedConfigCache, + ); + + const { files, references, composite } = parsed.options; + + // Detect ambiguous configurations + if (Array.isArray(files) && files.length === 0 && !references && !composite) { + parsed.errors.push( + createCompilerDiagnostic( + Diagnostics.No_actionable_task_Add_composite_Colon_true_valid_references_or_use_tsc_b, + ), + ); + + // Default to build mode to prevent silent failure + parsed.options.build = true; + } + + return parsed; } /** diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7f686076f1824..5d7b1b8fa6720 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4828,6 +4828,10 @@ "category": "Message", "code": 6041 }, + "No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'.": { + "category": "Message", + "code": 6042 + }, "Generates corresponding '.map' file.": { "category": "Message", "code": 6043 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 45d8539f581e3..07a4b01cca932 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1412,6 +1412,25 @@ export function getImpliedNodeFormatForFile(fileName: string, packageJsonInfoCac return typeof result === "object" ? result.impliedNodeFormat : result; } +/** + * Determines if the provided compiler configuration is ambiguous. + * + * A configuration is considered ambiguous if: + * - `rootNames` is an empty array + * - `options.composite` is false + * - `projectReferences` is undefined or an empty array + * - `options.include` is undefined or an empty array + * - `options.files` is undefined or an empty array + * + * @param options - The compiler options to check. + * @param rootNames - The root file names for the program. + * @param projectReferences - The project references for the program. + * @returns `true` if the configuration is ambiguous, otherwise `false`. + */ +export function isAmbiguousConfiguration(options: CompilerOptions, rootNames: readonly string[], projectReferences: readonly ProjectReference[] | undefined): boolean { + return (rootNames.length === 0 && !options.composite && (!projectReferences || projectReferences.length === 0) && (!options.include || (Array.isArray(options.include) && options.include.length === 0)) && (!options.files || (Array.isArray(options.files) && options.files.length === 0))); +} + /** @internal */ export function getImpliedNodeFormatForFileWorker( fileName: string, @@ -1595,7 +1614,8 @@ export function createProgram(createProgramOptions: CreateProgramOptions): Progr export function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program; export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program { const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 - const { rootNames, options, configFileParsingDiagnostics, projectReferences, typeScriptVersion } = createProgramOptions; + const { rootNames, options, projectReferences, typeScriptVersion } = createProgramOptions; + let configFileParsingDiagnostics = createProgramOptions.configFileParsingDiagnostics; let { oldProgram } = createProgramOptions; for (const option of commandLineOptionOfCustomType) { if (hasProperty(options, option.name)) { @@ -1605,6 +1625,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } + // Validate ambiguous configurations + if (options.configFilePath) { + const configPath = options.configFilePath; + if (isAmbiguousConfiguration(options, rootNames, projectReferences)) { + // Ensure diagnostics array is initialized + if (!configFileParsingDiagnostics) { + configFileParsingDiagnostics = []; + } + (configFileParsingDiagnostics as Diagnostic[]).push( + createCompilerDiagnostic( + Diagnostics.No_actionable_task_Add_composite_Colon_true_valid_references_or_use_tsc_b, + configPath, + ), + ); + } + } + const reportInvalidIgnoreDeprecations = memoize(() => createOptionValueDiagnostic("ignoreDeprecations", Diagnostics.Invalid_value_for_ignoreDeprecations)); let processingDefaultLibFiles: SourceFile[] | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 11a12e97d4b2e..d9906869976de 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -9553,6 +9553,22 @@ declare namespace ts { * @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format */ function getImpliedNodeFormatForFile(fileName: string, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode; + /** + * Determines if the provided compiler configuration is ambiguous. + * + * A configuration is considered ambiguous if: + * - `rootNames` is an empty array + * - `options.composite` is false + * - `projectReferences` is undefined or an empty array + * - `options.include` is undefined or an empty array + * - `options.files` is undefined or an empty array + * + * @param options - The compiler options to check. + * @param rootNames - The root file names for the program. + * @param projectReferences - The project references for the program. + * @returns `true` if the configuration is ambiguous, otherwise `false`. + */ + function isAmbiguousConfiguration(options: CompilerOptions, rootNames: readonly string[], projectReferences: readonly ProjectReference[] | undefined): boolean; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. diff --git a/tests/baselines/reference/containerProjectNoEmit.js b/tests/baselines/reference/containerProjectNoEmit.js new file mode 100644 index 0000000000000..52fcb63b56f8f --- /dev/null +++ b/tests/baselines/reference/containerProjectNoEmit.js @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/containerProjectNoEmit.ts] //// + +//// [containerProjectNoEmit.ts] +export const tsconfig = { + "files": [] +} + + +//// [containerProjectNoEmit.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tsconfig = void 0; +exports.tsconfig = { + "files": [] +}; diff --git a/tests/baselines/reference/containerProjectNoEmit.symbols b/tests/baselines/reference/containerProjectNoEmit.symbols new file mode 100644 index 0000000000000..66aa03f0722e3 --- /dev/null +++ b/tests/baselines/reference/containerProjectNoEmit.symbols @@ -0,0 +1,10 @@ +//// [tests/cases/compiler/containerProjectNoEmit.ts] //// + +=== containerProjectNoEmit.ts === +export const tsconfig = { +>tsconfig : Symbol(tsconfig, Decl(containerProjectNoEmit.ts, 0, 12)) + + "files": [] +>"files" : Symbol("files", Decl(containerProjectNoEmit.ts, 0, 25)) +} + diff --git a/tests/baselines/reference/containerProjectNoEmit.types b/tests/baselines/reference/containerProjectNoEmit.types new file mode 100644 index 0000000000000..158e208c5de31 --- /dev/null +++ b/tests/baselines/reference/containerProjectNoEmit.types @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/containerProjectNoEmit.ts] //// + +=== containerProjectNoEmit.ts === +export const tsconfig = { +>tsconfig : { files: any[]; } +> : ^^^^^^^^^^^^^^^^^ +>{ "files": []} : { files: undefined[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + "files": [] +>"files" : undefined[] +> : ^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js index 0a0189ac4c6d4..7579ef356fca6 100644 --- a/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js +++ b/tests/baselines/reference/declarationEmitToDeclarationDirWithDeclarationOption.js @@ -17,3 +17,20 @@ interface Foo { x: number; } export default Foo; + + +//// [DtsFileErrors] + + +message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. + + +!!! message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. +==== /foo/tsconfig.json (0 errors) ==== + { + "compilerOptions": { + "declaration": true, + "declarationDir": "out" + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/emptyFilesConfig.js b/tests/baselines/reference/emptyFilesConfig.js new file mode 100644 index 0000000000000..7e760f4bd6892 --- /dev/null +++ b/tests/baselines/reference/emptyFilesConfig.js @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/emptyFilesConfig.ts] //// + +//// [emptyFilesConfig.ts] +export const tsconfig = { + "files": [] +} + +//// [emptyFilesConfig.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tsconfig = void 0; +exports.tsconfig = { + "files": [] +}; diff --git a/tests/baselines/reference/emptyFilesConfig.symbols b/tests/baselines/reference/emptyFilesConfig.symbols new file mode 100644 index 0000000000000..b14322de64784 --- /dev/null +++ b/tests/baselines/reference/emptyFilesConfig.symbols @@ -0,0 +1,9 @@ +//// [tests/cases/compiler/emptyFilesConfig.ts] //// + +=== emptyFilesConfig.ts === +export const tsconfig = { +>tsconfig : Symbol(tsconfig, Decl(emptyFilesConfig.ts, 0, 12)) + + "files": [] +>"files" : Symbol("files", Decl(emptyFilesConfig.ts, 0, 25)) +} diff --git a/tests/baselines/reference/emptyFilesConfig.types b/tests/baselines/reference/emptyFilesConfig.types new file mode 100644 index 0000000000000..66dd10c2f7198 --- /dev/null +++ b/tests/baselines/reference/emptyFilesConfig.types @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/emptyFilesConfig.ts] //// + +=== emptyFilesConfig.ts === +export const tsconfig = { +>tsconfig : { files: any[]; } +> : ^^^^^^^^^^^^^^^^^ +>{ "files": []} : { files: undefined[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + "files": [] +>"files" : undefined[] +> : ^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +} diff --git a/tests/baselines/reference/filesWithReferences.js b/tests/baselines/reference/filesWithReferences.js new file mode 100644 index 0000000000000..37d771362f43e --- /dev/null +++ b/tests/baselines/reference/filesWithReferences.js @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/filesWithReferences.ts] //// + +//// [filesWithReferences.ts] +export const tsconfig = { + "files": [], + "references": [{ "path": "./lib" }] +} + + +//// [filesWithReferences.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tsconfig = void 0; +exports.tsconfig = { + "files": [], + "references": [{ "path": "./lib" }] +}; diff --git a/tests/baselines/reference/filesWithReferences.symbols b/tests/baselines/reference/filesWithReferences.symbols new file mode 100644 index 0000000000000..2400b00cb86de --- /dev/null +++ b/tests/baselines/reference/filesWithReferences.symbols @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/filesWithReferences.ts] //// + +=== filesWithReferences.ts === +export const tsconfig = { +>tsconfig : Symbol(tsconfig, Decl(filesWithReferences.ts, 0, 12)) + + "files": [], +>"files" : Symbol("files", Decl(filesWithReferences.ts, 0, 25)) + + "references": [{ "path": "./lib" }] +>"references" : Symbol("references", Decl(filesWithReferences.ts, 1, 16)) +>"path" : Symbol("path", Decl(filesWithReferences.ts, 2, 20)) +} + diff --git a/tests/baselines/reference/filesWithReferences.types b/tests/baselines/reference/filesWithReferences.types new file mode 100644 index 0000000000000..04f8be188c916 --- /dev/null +++ b/tests/baselines/reference/filesWithReferences.types @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/filesWithReferences.ts] //// + +=== filesWithReferences.ts === +export const tsconfig = { +>tsconfig : { files: any[]; references: { path: string; }[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ "files": [], "references": [{ "path": "./lib" }]} : { files: undefined[]; references: { path: string; }[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + "files": [], +>"files" : undefined[] +> : ^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + "references": [{ "path": "./lib" }] +>"references" : { path: string; }[] +> : ^^^^^^^^^^^^^^^^^^^ +>[{ "path": "./lib" }] : { path: string; }[] +> : ^^^^^^^^^^^^^^^^^^^ +>{ "path": "./lib" } : { path: string; } +> : ^^^^^^^^^^^^^^^^^ +>"path" : string +> : ^^^^^^ +>"./lib" : "./lib" +> : ^^^^^^^ +} + diff --git a/tests/baselines/reference/nodeAllowJsPackageSelfName2.errors.txt b/tests/baselines/reference/nodeAllowJsPackageSelfName2.errors.txt new file mode 100644 index 0000000000000..65d8ff1c6b2d3 --- /dev/null +++ b/tests/baselines/reference/nodeAllowJsPackageSelfName2.errors.txt @@ -0,0 +1,49 @@ +/test/foo.js(1,21): error TS2307: Cannot find module 'js-self-name-import/foo.js' or its corresponding type declarations. + + +==== /tsconfig.json (0 errors) ==== + { + "compilerOptions": { + "module": "nodenext", + "target": "esnext", + "emitDeclarationOnly": true, + "declaration": true, + "declarationDir": "./types", + "checkJs": true, + "rootDir": ".", + "strict": true, + "moduleResolution": "node16" // Ensures compatibility with Node's module resolution rules + }, + "include": ["src", "test"] + } + +==== /src/foo.js (0 errors) ==== + export const foo = 1; + +==== /test/foo.js (1 errors) ==== + import { foo } from "js-self-name-import/foo.js"; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'js-self-name-import/foo.js' or its corresponding type declarations. + +==== /package.json (0 errors) ==== + { + "name": "js-self-name-import", + "type": "module", + "exports": { + "./src/*": { + "types": "./types/src/*", + "default": "./src/*" + }, + "./test/*": { + "types": "./types/test/*", + "default": "./test/*" + } + } + } + +==== /types/src/foo.d.ts (0 errors) ==== + export const foo: 1; + +==== /types/test/foo.d.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/nodeAllowJsPackageSelfName2.js b/tests/baselines/reference/nodeAllowJsPackageSelfName2.js index 8d0b9db1924f9..d9a5bdb5cacfd 100644 --- a/tests/baselines/reference/nodeAllowJsPackageSelfName2.js +++ b/tests/baselines/reference/nodeAllowJsPackageSelfName2.js @@ -5,12 +5,16 @@ "name": "js-self-name-import", "type": "module", "exports": { - "./*": { - "types": "./types/src/*", - "default": "./src/*" - } + "./src/*": { + "types": "./types/src/*", + "default": "./src/*" + }, + "./test/*": { + "types": "./types/test/*", + "default": "./test/*" } } +} //// [foo.d.ts] export const foo: 1; diff --git a/tests/baselines/reference/nodeAllowJsPackageSelfName2.types b/tests/baselines/reference/nodeAllowJsPackageSelfName2.types index 31c7d37447ee6..0bfa6f35596cb 100644 --- a/tests/baselines/reference/nodeAllowJsPackageSelfName2.types +++ b/tests/baselines/reference/nodeAllowJsPackageSelfName2.types @@ -9,6 +9,6 @@ export const foo = 1; === /test/foo.js === import { foo } from "js-self-name-import/foo.js"; ->foo : 1 -> : ^ +>foo : any +> : ^^^ diff --git a/tests/baselines/reference/solutionStyleRoot.js b/tests/baselines/reference/solutionStyleRoot.js new file mode 100644 index 0000000000000..613bdf7bd1d1a --- /dev/null +++ b/tests/baselines/reference/solutionStyleRoot.js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/solutionStyleRoot.ts] //// + +//// [solutionStyleRoot.ts] +export const tsconfig = { + "references": [ + { "path": "./lib" }, + { "path": "./app" } + ] +} + + +//// [solutionStyleRoot.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tsconfig = void 0; +exports.tsconfig = { + "references": [ + { "path": "./lib" }, + { "path": "./app" } + ] +}; diff --git a/tests/baselines/reference/solutionStyleRoot.symbols b/tests/baselines/reference/solutionStyleRoot.symbols new file mode 100644 index 0000000000000..ae99b4481fa71 --- /dev/null +++ b/tests/baselines/reference/solutionStyleRoot.symbols @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/solutionStyleRoot.ts] //// + +=== solutionStyleRoot.ts === +export const tsconfig = { +>tsconfig : Symbol(tsconfig, Decl(solutionStyleRoot.ts, 0, 12)) + + "references": [ +>"references" : Symbol("references", Decl(solutionStyleRoot.ts, 0, 25)) + + { "path": "./lib" }, +>"path" : Symbol("path", Decl(solutionStyleRoot.ts, 2, 9)) + + { "path": "./app" } +>"path" : Symbol("path", Decl(solutionStyleRoot.ts, 3, 9)) + + ] +} + diff --git a/tests/baselines/reference/solutionStyleRoot.types b/tests/baselines/reference/solutionStyleRoot.types new file mode 100644 index 0000000000000..d2845a676e3ad --- /dev/null +++ b/tests/baselines/reference/solutionStyleRoot.types @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/solutionStyleRoot.ts] //// + +=== solutionStyleRoot.ts === +export const tsconfig = { +>tsconfig : { references: { path: string; }[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ "references": [ { "path": "./lib" }, { "path": "./app" } ]} : { references: { path: string; }[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + "references": [ +>"references" : { path: string; }[] +> : ^^^^^^^^^^^^^^^^^^^ +>[ { "path": "./lib" }, { "path": "./app" } ] : { path: string; }[] +> : ^^^^^^^^^^^^^^^^^^^ + + { "path": "./lib" }, +>{ "path": "./lib" } : { path: string; } +> : ^^^^^^^^^^^^^^^^^ +>"path" : string +> : ^^^^^^ +>"./lib" : "./lib" +> : ^^^^^^^ + + { "path": "./app" } +>{ "path": "./app" } : { path: string; } +> : ^^^^^^^^^^^^^^^^^ +>"path" : string +> : ^^^^^^ +>"./app" : "./app" +> : ^^^^^^^ + + ] +} + diff --git a/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-able-to-handle-@types-if-input-file-list-is-empty.js b/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-able-to-handle-@types-if-input-file-list-is-empty.js index 21bef29316890..037e89d0ce5d4 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-able-to-handle-@types-if-input-file-list-is-empty.js +++ b/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-able-to-handle-@types-if-input-file-list-is-empty.js @@ -36,6 +36,8 @@ Output:: >> Screen clear [HH:MM:SS AM] Starting compilation in watch mode... +message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. + tsconfig.json:3:12 - error TS18002: The 'files' list in config file '/user/username/workspace/solution/projects/project/tsconfig.json' is empty. 3 "files": [] diff --git a/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-tolerated-without-crashing-the-server.js b/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-tolerated-without-crashing-the-server.js index 104584d19cbe5..cdb6468d83f93 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-tolerated-without-crashing-the-server.js +++ b/tests/baselines/reference/tscWatch/programUpdates/non-existing-directories-listed-in-config-file-input-array-should-be-tolerated-without-crashing-the-server.js @@ -30,6 +30,8 @@ Output:: >> Screen clear [HH:MM:SS AM] Starting compilation in watch mode... +message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. + error TS18003: No inputs were found in config file '/user/username/workspace/solution/projects/project/tsconfig.json'. Specified 'include' paths were '["app/*","test/**/*","something"]' and 'exclude' paths were '[]'. [HH:MM:SS AM] Found 1 error. Watching for file changes. diff --git a/tests/baselines/reference/validCompositeProject.js b/tests/baselines/reference/validCompositeProject.js new file mode 100644 index 0000000000000..0f1bbe1bb9f7e --- /dev/null +++ b/tests/baselines/reference/validCompositeProject.js @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/validCompositeProject.ts] //// + +//// [validCompositeProject.ts] +export const tsconfig = { + "files": [], + "composite": true +}; + +//// [validCompositeProject.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tsconfig = void 0; +exports.tsconfig = { + "files": [], + "composite": true +}; diff --git a/tests/baselines/reference/validCompositeProject.symbols b/tests/baselines/reference/validCompositeProject.symbols new file mode 100644 index 0000000000000..902bc86b9eb5c --- /dev/null +++ b/tests/baselines/reference/validCompositeProject.symbols @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/validCompositeProject.ts] //// + +=== validCompositeProject.ts === +export const tsconfig = { +>tsconfig : Symbol(tsconfig, Decl(validCompositeProject.ts, 0, 12)) + + "files": [], +>"files" : Symbol("files", Decl(validCompositeProject.ts, 0, 25)) + + "composite": true +>"composite" : Symbol("composite", Decl(validCompositeProject.ts, 1, 16)) + +}; diff --git a/tests/baselines/reference/validCompositeProject.types b/tests/baselines/reference/validCompositeProject.types new file mode 100644 index 0000000000000..283ad0dffdb74 --- /dev/null +++ b/tests/baselines/reference/validCompositeProject.types @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/validCompositeProject.ts] //// + +=== validCompositeProject.ts === +export const tsconfig = { +>tsconfig : { files: any[]; composite: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ "files": [], "composite": true} : { files: undefined[]; composite: boolean; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + "files": [], +>"files" : undefined[] +> : ^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + "composite": true +>"composite" : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +}; diff --git a/tests/cases/compiler/containerProjectNoEmit.ts b/tests/cases/compiler/containerProjectNoEmit.ts new file mode 100644 index 0000000000000..7710a88738485 --- /dev/null +++ b/tests/cases/compiler/containerProjectNoEmit.ts @@ -0,0 +1,3 @@ +export const tsconfig = { + "files": [] +} diff --git a/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts b/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts index e3d4231a8f6c0..957891117bde1 100644 --- a/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts +++ b/tests/cases/compiler/declarationEmitToDeclarationDirWithDeclarationOption.ts @@ -1,8 +1,11 @@ // @declaration: true // @filename: /foo/tsconfig.json { - "compilerOptions": { "declaration": true, "declarationDir": "out" } -} + "compilerOptions": { + "declaration": true, + "declarationDir": "out" + } + } // @filename: /foo/test.ts interface Foo { diff --git a/tests/cases/compiler/emptyFilesConfig.ts b/tests/cases/compiler/emptyFilesConfig.ts new file mode 100644 index 0000000000000..07be2a11f3015 --- /dev/null +++ b/tests/cases/compiler/emptyFilesConfig.ts @@ -0,0 +1,3 @@ +export const tsconfig = { + "files": [] +} \ No newline at end of file diff --git a/tests/cases/compiler/filesWithReferences.ts b/tests/cases/compiler/filesWithReferences.ts new file mode 100644 index 0000000000000..a3b0dc19d3117 --- /dev/null +++ b/tests/cases/compiler/filesWithReferences.ts @@ -0,0 +1,4 @@ +export const tsconfig = { + "files": [], + "references": [{ "path": "./lib" }] +} diff --git a/tests/cases/compiler/solutionStyleRoot.ts b/tests/cases/compiler/solutionStyleRoot.ts new file mode 100644 index 0000000000000..c3e7783f98162 --- /dev/null +++ b/tests/cases/compiler/solutionStyleRoot.ts @@ -0,0 +1,6 @@ +export const tsconfig = { + "references": [ + { "path": "./lib" }, + { "path": "./app" } + ] +} diff --git a/tests/cases/compiler/validCompositeProject.ts b/tests/cases/compiler/validCompositeProject.ts new file mode 100644 index 0000000000000..43491ee0db5e2 --- /dev/null +++ b/tests/cases/compiler/validCompositeProject.ts @@ -0,0 +1,5 @@ + +export const tsconfig = { + "files": [], + "composite": true +}; \ No newline at end of file diff --git a/tests/cases/conformance/node/allowJs/nodeAllowJsPackageSelfName2.ts b/tests/cases/conformance/node/allowJs/nodeAllowJsPackageSelfName2.ts index 5aa706a15a082..ee79888213f01 100644 --- a/tests/cases/conformance/node/allowJs/nodeAllowJsPackageSelfName2.ts +++ b/tests/cases/conformance/node/allowJs/nodeAllowJsPackageSelfName2.ts @@ -1,6 +1,6 @@ // @Filename: /tsconfig.json { - "compilerOptions": { +"compilerOptions": { "module": "nodenext", "target": "esnext", "emitDeclarationOnly": true, @@ -9,6 +9,7 @@ "checkJs": true, "rootDir": ".", "strict": true, + "moduleResolution": "node16" // Ensures compatibility with Node's module resolution rules }, "include": ["src", "test"] } @@ -18,12 +19,16 @@ "name": "js-self-name-import", "type": "module", "exports": { - "./*": { - "types": "./types/src/*", - "default": "./src/*" - } + "./src/*": { + "types": "./types/src/*", + "default": "./src/*" + }, + "./test/*": { + "types": "./types/test/*", + "default": "./test/*" } } +} // @Filename: /types/src/foo.d.ts export const foo: 1; From 61a4ddf5f21e2bce79fa1079b8c9f8fda2ede039 Mon Sep 17 00:00:00 2001 From: Ryan Myrvold <2127198+RyanMyrvold@users.noreply.github.com> Date: Sat, 23 Nov 2024 23:07:55 -0500 Subject: [PATCH 2/2] Initialization Logic, Ambiguous Configurations and Update and Accept Baselines Verified and accepted changes to ensure consistency with the expected output. Fixed a bug where configFileParsingDiagnostics could be undefined, causing runtime errors (Cannot read properties of undefined (reading 'push')). Added guards to ensure diagnostics arrays are always initialized before use. Improved code resilience and prevented potential runtime errors in edge cases. --- ...tedConfigurationsWithFilesEmpty.errors.txt | 23 +++++++++++++++++++ .../compiler/compositeWithoutReferences.ts | 13 +++++++++++ .../nestedConfigurationsWithFilesEmpty.ts | 19 +++++++++++++++ .../compiler/noEmitBehaviorWithFilesEmpty.ts | 12 ++++++++++ 4 files changed, 67 insertions(+) create mode 100644 tests/baselines/reference/nestedConfigurationsWithFilesEmpty.errors.txt create mode 100644 tests/cases/compiler/compositeWithoutReferences.ts create mode 100644 tests/cases/compiler/nestedConfigurationsWithFilesEmpty.ts create mode 100644 tests/cases/compiler/noEmitBehaviorWithFilesEmpty.ts diff --git a/tests/baselines/reference/nestedConfigurationsWithFilesEmpty.errors.txt b/tests/baselines/reference/nestedConfigurationsWithFilesEmpty.errors.txt new file mode 100644 index 0000000000000..d7804f0fe6a39 --- /dev/null +++ b/tests/baselines/reference/nestedConfigurationsWithFilesEmpty.errors.txt @@ -0,0 +1,23 @@ +message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. + + +!!! message TS6042: No actionable task. Add 'composite': true, valid 'references', or use 'tsc -b'. +==== /parent/tsconfig.json (0 errors) ==== + { + "files": [], + "references": [{ "path": "../child" }] + } + + // @filename: /child/tsconfig.json + { + "compilerOptions": { + "declaration": true, + "declarationDir": "out", + "composite": true + }, + "include": ["index.ts"] + } + + // @filename: /child/index.ts + export const childConst = "I am child!"; + \ No newline at end of file diff --git a/tests/cases/compiler/compositeWithoutReferences.ts b/tests/cases/compiler/compositeWithoutReferences.ts new file mode 100644 index 0000000000000..8d88aa75efa1e --- /dev/null +++ b/tests/cases/compiler/compositeWithoutReferences.ts @@ -0,0 +1,13 @@ +// @filename: /tsconfig.json +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "out", + "composite": true + }, + "files": [] + } + + // @filename: /src/index.ts + export const compositeTest = "Composite test case"; + \ No newline at end of file diff --git a/tests/cases/compiler/nestedConfigurationsWithFilesEmpty.ts b/tests/cases/compiler/nestedConfigurationsWithFilesEmpty.ts new file mode 100644 index 0000000000000..b50a6c9f8dbf3 --- /dev/null +++ b/tests/cases/compiler/nestedConfigurationsWithFilesEmpty.ts @@ -0,0 +1,19 @@ +// @filename: /parent/tsconfig.json +{ + "files": [], + "references": [{ "path": "../child" }] + } + + // @filename: /child/tsconfig.json + { + "compilerOptions": { + "declaration": true, + "declarationDir": "out", + "composite": true + }, + "include": ["index.ts"] + } + + // @filename: /child/index.ts + export const childConst = "I am child!"; + \ No newline at end of file diff --git a/tests/cases/compiler/noEmitBehaviorWithFilesEmpty.ts b/tests/cases/compiler/noEmitBehaviorWithFilesEmpty.ts new file mode 100644 index 0000000000000..a71df104310af --- /dev/null +++ b/tests/cases/compiler/noEmitBehaviorWithFilesEmpty.ts @@ -0,0 +1,12 @@ +// @filename: /tsconfig.json +{ + "compilerOptions": { + "noEmit": true, + "composite": true + }, + "files": [] + } + + // @filename: /src/index.ts + export const noEmitTest = "This shouldn't emit"; + \ No newline at end of file