diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index bc7a8673943..17e90bd6225 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -333,7 +333,13 @@ namespace ts { * This is to allow the callers to be able to actually remove affected file only when the operation is complete * eg. if during diagnostics check cancellation token ends up cancelling the request, the affected file should be retained */ - function getNextAffectedFile(state: BuilderProgramState, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, host: BuilderProgramHost): SourceFile | Program | undefined { + function getNextAffectedFile( + state: BuilderProgramState, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost + ): SourceFile | Program | undefined { while (true) { const { affectedFiles } = state; if (affectedFiles) { @@ -344,7 +350,14 @@ namespace ts { if (!seenAffectedFiles.has(affectedFile.resolvedPath)) { // Set the next affected file as seen and remove the cached semantic diagnostics state.affectedFilesIndex = affectedFilesIndex; - handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, computeHash, host); + handleDtsMayChangeOfAffectedFile( + state, + affectedFile, + cancellationToken, + computeHash, + getCanonicalFileName, + host + ); return affectedFile; } affectedFilesIndex++; @@ -376,7 +389,14 @@ namespace ts { } // Get next batch of affected files - state.affectedFiles = BuilderState.getFilesAffectedByWithOldState(state, program, nextKey.value, cancellationToken, computeHash); + state.affectedFiles = BuilderState.getFilesAffectedByWithOldState( + state, + program, + nextKey.value, + cancellationToken, + computeHash, + getCanonicalFileName, + ); state.currentChangedFilePath = nextKey.value; state.affectedFilesIndex = 0; if (!state.seenAffectedFiles) state.seenAffectedFiles = new Set(); @@ -435,6 +455,7 @@ namespace ts { affectedFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, host: BuilderProgramHost, ) { removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath); @@ -451,11 +472,19 @@ namespace ts { affectedFile, cancellationToken, computeHash, + getCanonicalFileName, ); return; } if (state.compilerOptions.assumeChangesOnlyAffectDirectDependencies) return; - handleDtsMayChangeOfReferencingExportOfAffectedFile(state, affectedFile, cancellationToken, computeHash, host); + handleDtsMayChangeOfReferencingExportOfAffectedFile( + state, + affectedFile, + cancellationToken, + computeHash, + getCanonicalFileName, + host, + ); } /** @@ -467,6 +496,7 @@ namespace ts { path: Path, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, host: BuilderProgramHost ): void { removeSemanticDiagnosticsOf(state, path); @@ -486,6 +516,7 @@ namespace ts { sourceFile, cancellationToken, computeHash, + getCanonicalFileName, !host.disableUseFileVersionAsSignature ); // If not dts emit, nothing more to do @@ -520,6 +551,7 @@ namespace ts { filePath: Path, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, host: BuilderProgramHost, ): boolean { if (!state.fileInfos.get(filePath)?.affectsGlobalScope) return false; @@ -530,6 +562,7 @@ namespace ts { file.resolvedPath, cancellationToken, computeHash, + getCanonicalFileName, host, )); removeDiagnosticsOfLibraryFiles(state); @@ -544,6 +577,7 @@ namespace ts { affectedFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, host: BuilderProgramHost ) { // If there was change in signature (dts output) for the changed file, @@ -561,8 +595,8 @@ namespace ts { const currentPath = queue.pop()!; if (!seenFileNamesMap.has(currentPath)) { seenFileNamesMap.set(currentPath, true); - if (handleDtsMayChangeOfGlobalScope(state, currentPath, cancellationToken, computeHash, host)) return; - handleDtsMayChangeOf(state, currentPath, cancellationToken, computeHash, host); + if (handleDtsMayChangeOfGlobalScope(state, currentPath, cancellationToken, computeHash, getCanonicalFileName, host)) return; + handleDtsMayChangeOf(state, currentPath, cancellationToken, computeHash, getCanonicalFileName, host); if (isChangedSignature(state, currentPath)) { const currentSourceFile = Debug.checkDefined(state.program).getSourceFileByPath(currentPath)!; queue.push(...BuilderState.getReferencedByPaths(state, currentSourceFile.resolvedPath)); @@ -575,7 +609,7 @@ namespace ts { // Go through exported modules from cache first // If exported modules has path, all files referencing file exported from are affected state.exportedModulesMap.getKeys(affectedFile.resolvedPath)?.forEach(exportedFromPath => { - if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, cancellationToken, computeHash, host)) return true; + if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, cancellationToken, computeHash, getCanonicalFileName, host)) return true; const references = state.referencedMap!.getKeys(exportedFromPath); return references && forEachKey(references, filePath => handleDtsMayChangeOfFileAndExportsOfFile( @@ -584,6 +618,7 @@ namespace ts { seenFileAndExportsOfFile, cancellationToken, computeHash, + getCanonicalFileName, host, ) ); @@ -600,12 +635,13 @@ namespace ts { seenFileAndExportsOfFile: Set, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, host: BuilderProgramHost, ): boolean | undefined { if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; - if (handleDtsMayChangeOfGlobalScope(state, filePath, cancellationToken, computeHash, host)) return true; - handleDtsMayChangeOf(state, filePath, cancellationToken, computeHash, host); + if (handleDtsMayChangeOfGlobalScope(state, filePath, cancellationToken, computeHash, getCanonicalFileName, host)) return true; + handleDtsMayChangeOf(state, filePath, cancellationToken, computeHash, getCanonicalFileName, host); // If exported modules has path, all files referencing file exported from are affected state.exportedModulesMap!.getKeys(filePath)?.forEach(exportedFromPath => @@ -615,6 +651,7 @@ namespace ts { seenFileAndExportsOfFile, cancellationToken, computeHash, + getCanonicalFileName, host, ) ); @@ -627,6 +664,7 @@ namespace ts { referencingFilePath, cancellationToken, computeHash, + getCanonicalFileName, host, ) ); @@ -1038,8 +1076,45 @@ namespace ts { return { host, newProgram, oldProgram, configFileParsingDiagnostics: configFileParsingDiagnostics || emptyArray }; } - export function computeSignature(text: string, data: WriteFileCallbackData | undefined, computeHash: BuilderState.ComputeHash | undefined) { - return BuilderState.computeSignature(data?.sourceMapUrlPos !== undefined ? text.substring(0, data.sourceMapUrlPos) : text, computeHash); + function getTextHandlingSourceMapForSignature(text: string, data: WriteFileCallbackData | undefined) { + return data?.sourceMapUrlPos !== undefined ? text.substring(0, data.sourceMapUrlPos) : text; + } + + export function computeSignatureWithDiagnostics( + sourceFile: SourceFile, + text: string, + computeHash: BuilderState.ComputeHash | undefined, + getCanonicalFileName: GetCanonicalFileName, + data: WriteFileCallbackData | undefined + ) { + text = getTextHandlingSourceMapForSignature(text, data); + let sourceFileDirectory: string | undefined; + if (data?.diagnostics?.length) { + text += data.diagnostics.map(diagnostic => + `${locationInfo(diagnostic)}${DiagnosticCategory[diagnostic.category]}${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText)}` + ).join("\n"); + } + return (computeHash ?? generateDjb2Hash)(text); + + function flattenDiagnosticMessageText(diagnostic: string | DiagnosticMessageChain | undefined): string { + return isString(diagnostic) ? + diagnostic : + diagnostic === undefined ? + "" : + !diagnostic.next ? + diagnostic.messageText : + diagnostic.messageText + diagnostic.next.map(flattenDiagnosticMessageText).join("\n"); + } + + function locationInfo(diagnostic: DiagnosticWithLocation) { + if (diagnostic.file.resolvedPath === sourceFile.resolvedPath) return `(${diagnostic.start},${diagnostic.length})`; + if (sourceFileDirectory === undefined) sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath); + return `${ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceFileDirectory, diagnostic.file.resolvedPath, getCanonicalFileName))}(${diagnostic.start},${diagnostic.length})`; + } + } + + export function computeSignature(text: string, computeHash: BuilderState.ComputeHash | undefined, data?: WriteFileCallbackData) { + return (computeHash ?? generateDjb2Hash)(getTextHandlingSourceMapForSignature(text, data)); } export function createBuilderProgram(kind: BuilderProgramKind.SemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): SemanticDiagnosticsBuilderProgram; @@ -1108,7 +1183,7 @@ namespace ts { * in that order would be used to write the files */ function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult { - let affected = getNextAffectedFile(state, cancellationToken, computeHash, host); + let affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host); let emitKind = BuilderFileEmit.Full; let isPendingEmitFile = false; if (!affected) { @@ -1165,24 +1240,32 @@ namespace ts { if (isDeclarationFileName(fileName)) { if (!outFile(state.compilerOptions)) { Debug.assert(sourceFiles?.length === 1); - let newSignature; + let emitSignature; if (!customTransformers) { const file = sourceFiles[0]; const info = state.fileInfos.get(file.resolvedPath)!; if (info.signature === file.version) { - newSignature = computeSignature(text, data, computeHash); - if (newSignature !== file.version) { // Update it - if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ||= new Set()).add(file.resolvedPath); + const signature = computeSignatureWithDiagnostics( + file, + text, + computeHash, + getCanonicalFileName, + data, + ); + // With d.ts diagnostics they are also part of the signature so emitSignature will be different from it since its just hash of d.ts + if (!data?.diagnostics?.length) emitSignature = signature; + if (signature !== file.version) { // Update it + if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ??= new Set()).add(file.resolvedPath); if (state.exportedModulesMap) BuilderState.updateExportedModules(state, file, file.exportedModulesFromDeclarationEmit); if (state.affectedFiles) { // Keep old signature so we know what to undo if cancellation happens const existing = state.oldSignatures?.get(file.resolvedPath); - if (existing === undefined) (state.oldSignatures ||= new Map()).set(file.resolvedPath, info.signature || false); - info.signature = newSignature; + if (existing === undefined) (state.oldSignatures ??= new Map()).set(file.resolvedPath, info.signature || false); + info.signature = signature; } else { // These are directly commited - info.signature = newSignature; + info.signature = signature; state.oldExportedModulesMap?.clear(); } } @@ -1195,15 +1278,15 @@ namespace ts { if (state.compilerOptions.composite) { const filePath = sourceFiles[0].resolvedPath; const oldSignature = state.emitSignatures?.get(filePath); - newSignature ||= computeSignature(text, data, computeHash); - if (newSignature !== oldSignature) { - (state.emitSignatures ||= new Map()).set(filePath, newSignature); + emitSignature ??= computeSignature(text, computeHash, data); + if (emitSignature !== oldSignature) { + (state.emitSignatures ??= new Map()).set(filePath, emitSignature); state.hasChangedEmitSignature = true; } } } else if (state.compilerOptions.composite) { - const newSignature = computeSignature(text, data, computeHash); + const newSignature = computeSignature(text, computeHash, data); if (newSignature !== state.outSignature) { state.outSignature = newSignature; state.hasChangedEmitSignature = true; @@ -1287,7 +1370,7 @@ namespace ts { */ function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult { while (true) { - const affected = getNextAffectedFile(state, cancellationToken, computeHash, host); + const affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host); if (!affected) { // Done return undefined; diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 4be044c0355..de300efd3cf 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -3,8 +3,8 @@ namespace ts { export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitOutput { const outputFiles: OutputFile[] = []; - const { emitSkipped, diagnostics, exportedModulesFromDeclarationEmit } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); - return { outputFiles, emitSkipped, diagnostics, exportedModulesFromDeclarationEmit }; + const { emitSkipped, diagnostics } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); + return { outputFiles, emitSkipped, diagnostics }; function writeFile(fileName: string, text: string, writeByteOrderMark: boolean) { outputFiles.push({ name: fileName, writeByteOrderMark, text }); @@ -321,24 +321,45 @@ namespace ts { /** * Gets the files affected by the path from the program */ - export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash): readonly SourceFile[] { - const result = getFilesAffectedByWithOldState(state, programOfThisState, path, cancellationToken, computeHash); + export function getFilesAffectedBy( + state: BuilderState, + programOfThisState: Program, + path: Path, + cancellationToken: CancellationToken | undefined, + computeHash: ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + ): readonly SourceFile[] { + const result = getFilesAffectedByWithOldState( + state, + programOfThisState, + path, + cancellationToken, + computeHash, + getCanonicalFileName, + ); state.oldSignatures?.clear(); state.oldExportedModulesMap?.clear(); return result; } - export function getFilesAffectedByWithOldState(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash): readonly SourceFile[] { + export function getFilesAffectedByWithOldState( + state: BuilderState, + programOfThisState: Program, + path: Path, + cancellationToken: CancellationToken | undefined, + computeHash: ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + ): readonly SourceFile[] { const sourceFile = programOfThisState.getSourceFileByPath(path); if (!sourceFile) { return emptyArray; } - if (!updateShapeSignature(state, programOfThisState, sourceFile, cancellationToken, computeHash)) { + if (!updateShapeSignature(state, programOfThisState, sourceFile, cancellationToken, computeHash, getCanonicalFileName)) { return [sourceFile]; } - return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, cancellationToken, computeHash); + return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, cancellationToken, computeHash, getCanonicalFileName); } export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path) { @@ -349,7 +370,15 @@ namespace ts { /** * Returns if the shape of the signature has changed since last emit */ - export function updateShapeSignature(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, useFileVersionAsSignature = state.useFileVersionAsSignature) { + export function updateShapeSignature( + state: BuilderState, + programOfThisState: Program, + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + useFileVersionAsSignature = state.useFileVersionAsSignature + ) { // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate if (state.hasCalledUpdateShapeSignature?.has(sourceFile.resolvedPath)) return false; @@ -357,22 +386,26 @@ namespace ts { const prevSignature = info.signature; let latestSignature: string | undefined; if (!sourceFile.isDeclarationFile && !useFileVersionAsSignature) { - const emitOutput = getFileEmitOutput( - programOfThisState, + programOfThisState.emit( sourceFile, - /*emitOnlyDtsFiles*/ true, + (fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => { + Debug.assert(isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`); + latestSignature = computeSignatureWithDiagnostics( + sourceFile, + text, + computeHash, + getCanonicalFileName, + data, + ); + if (latestSignature !== prevSignature) { + updateExportedModules(state, sourceFile, sourceFiles![0].exportedModulesFromDeclarationEmit); + } + }, cancellationToken, + /*emitOnlyDtsFiles*/ true, /*customTransformers*/ undefined, /*forceDtsEmit*/ true ); - const firstDts = firstOrUndefined(emitOutput.outputFiles); - if (firstDts) { - Debug.assert(isDeclarationFileName(firstDts.name), "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))}`); - latestSignature = computeSignature(firstDts.text, computeHash); - if (latestSignature !== prevSignature) { - updateExportedModules(state, sourceFile, emitOutput.exportedModulesFromDeclarationEmit); - } - } } // Default is to use file version as signature if (latestSignature === undefined) { @@ -395,10 +428,6 @@ namespace ts { return latestSignature !== prevSignature; } - export function computeSignature(text: string, computeHash: ComputeHash | undefined) { - return (computeHash || generateDjb2Hash)(text); - } - /** * Coverts the declaration emit result into exported modules map */ @@ -556,7 +585,14 @@ namespace ts { /** * When program emits modular code, gets the files affected by the sourceFile whose shape has changed */ - function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash) { + function getFilesAffectedByUpdatedShapeWhenModuleEmit( + state: BuilderState, + programOfThisState: Program, + sourceFileWithUpdatedShape: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + ) { if (isFileAffectingGlobalScope(sourceFileWithUpdatedShape)) { return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); } @@ -579,7 +615,7 @@ namespace ts { if (!seenFileNamesMap.has(currentPath)) { const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!; seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cancellationToken, computeHash)) { + if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cancellationToken, computeHash, getCanonicalFileName)) { queue.push(...getReferencedByPaths(state, currentSourceFile.resolvedPath)); } } diff --git a/src/compiler/builderStatePublic.ts b/src/compiler/builderStatePublic.ts index 6a9495d27d4..29c6b61ef36 100644 --- a/src/compiler/builderStatePublic.ts +++ b/src/compiler/builderStatePublic.ts @@ -3,7 +3,6 @@ namespace ts { outputFiles: OutputFile[]; emitSkipped: boolean; /* @internal */ diagnostics: readonly Diagnostic[]; - /* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit; } export interface OutputFile { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6759e51ef1f..98b7f3cde54 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -288,7 +288,6 @@ namespace ts { const { enter, exit } = performance.createTimer("printTime", "beforePrint", "afterPrint"); let bundleBuildInfo: BundleBuildInfo | undefined; let emitSkipped = false; - let exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined; // Emit each output file enter(); @@ -308,7 +307,6 @@ namespace ts { diagnostics: emitterDiagnostics.getDiagnostics(), emittedFiles: emittedFilesList, sourceMaps: sourceMapDataList, - exportedModulesFromDeclarationEmit }; function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) { @@ -414,7 +412,7 @@ namespace ts { }); Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); - printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], printer, compilerOptions); + printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform, printer, compilerOptions); // Clean up emit nodes on parse tree transform.dispose(); @@ -453,7 +451,7 @@ namespace ts { noEmitHelpers: true, module: compilerOptions.module, target: compilerOptions.target, - sourceMap: compilerOptions.sourceMap, + sourceMap: !forceDtsEmit && compilerOptions.declarationMap, inlineSourceMap: compilerOptions.inlineSourceMap, extendedDiagnostics: compilerOptions.extendedDiagnostics, onlyPrintJsDocStyle: true, @@ -478,20 +476,16 @@ namespace ts { printSourceFileOrBundle( declarationFilePath, declarationMapPath, - declarationTransform.transformed[0], + declarationTransform, declarationPrinter, { - sourceMap: !forceDtsEmit && compilerOptions.declarationMap, + sourceMap: printerOptions.sourceMap, sourceRoot: compilerOptions.sourceRoot, mapRoot: compilerOptions.mapRoot, extendedDiagnostics: compilerOptions.extendedDiagnostics, // Explicitly do not passthru either `inline` option } ); - if (forceDtsEmit && declarationTransform.transformed[0].kind === SyntaxKind.SourceFile) { - const sourceFile = declarationTransform.transformed[0]; - exportedModulesFromDeclarationEmit = sourceFile.exportedModulesFromDeclarationEmit; - } } declarationTransform.dispose(); if (bundleBuildInfo) bundleBuildInfo.dts = declarationPrinter.bundleFileInfo; @@ -511,7 +505,8 @@ namespace ts { forEachChild(node, collectLinkedAliases); } - function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, mapOptions: SourceMapOptions) { + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, transform: TransformationResult, printer: Printer, mapOptions: SourceMapOptions) { + const sourceFileOrBundle = transform.transformed[0]; const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile!]; @@ -559,7 +554,7 @@ namespace ts { if (sourceMapFilePath) { const sourceMap = sourceMapGenerator.toString(); writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap, /*writeByteOrderMark*/ false, sourceFiles); - if (printer.bundleFileInfo) printer.bundleFileInfo.mapHash = BuilderState.computeSignature(sourceMap, maybeBind(host, host.createHash)); + if (printer.bundleFileInfo) printer.bundleFileInfo.mapHash = computeSignature(sourceMap, maybeBind(host, host.createHash)); } } else { @@ -568,10 +563,10 @@ namespace ts { // Write the output file const text = writer.getText(); - writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos }); + writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos, diagnostics: transform.diagnostics }); // We store the hash of the text written in the buildinfo to ensure that text of the referenced d.ts file is same as whats in the buildinfo // This is needed because incremental can be toggled between two runs and we might use stale file text to do text manipulation in prepend mode - if (printer.bundleFileInfo) printer.bundleFileInfo.hash = BuilderState.computeSignature(text, maybeBind(host, host.createHash)); + if (printer.bundleFileInfo) printer.bundleFileInfo.hash = computeSignature(text, maybeBind(host, host.createHash)); // Reset state writer.clear(); @@ -774,20 +769,20 @@ namespace ts { const jsFileText = host.readFile(Debug.checkDefined(jsFilePath)); if (!jsFileText) return jsFilePath!; // If the jsFileText is not same has what it was created with, tsbuildinfo is stale so dont use it - if (BuilderState.computeSignature(jsFileText, createHash) !== buildInfo.bundle.js.hash) return jsFilePath!; + if (computeSignature(jsFileText, createHash) !== buildInfo.bundle.js.hash) return jsFilePath!; const sourceMapText = sourceMapFilePath && host.readFile(sourceMapFilePath); // error if no source map or for now if inline sourcemap if ((sourceMapFilePath && !sourceMapText) || config.options.inlineSourceMap) return sourceMapFilePath || "inline sourcemap decoding"; - if (sourceMapFilePath && BuilderState.computeSignature(sourceMapText!, createHash) !== buildInfo.bundle.js.mapHash) return sourceMapFilePath; + if (sourceMapFilePath && computeSignature(sourceMapText!, createHash) !== buildInfo.bundle.js.mapHash) return sourceMapFilePath; // read declaration text const declarationText = declarationFilePath && host.readFile(declarationFilePath); if (declarationFilePath && !declarationText) return declarationFilePath; - if (declarationFilePath && BuilderState.computeSignature(declarationText!, createHash) !== buildInfo.bundle.dts!.hash) return declarationFilePath; + if (declarationFilePath && computeSignature(declarationText!, createHash) !== buildInfo.bundle.dts!.hash) return declarationFilePath; const declarationMapText = declarationMapPath && host.readFile(declarationMapPath); // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - if (declarationMapPath && BuilderState.computeSignature(declarationMapText!, createHash) !== buildInfo.bundle.dts!.mapHash) return declarationMapPath; + if (declarationMapPath && computeSignature(declarationMapText!, createHash) !== buildInfo.bundle.dts!.mapHash) return declarationMapPath; const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); const ownPrependInput = createInputFiles( @@ -836,7 +831,7 @@ namespace ts { newBuildInfo.program = buildInfo.program; if (newBuildInfo.program && changedDtsText !== undefined && config.options.composite) { // Update the output signature - (newBuildInfo.program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, changedDtsData, createHash); + (newBuildInfo.program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData); newBuildInfo.program.dtsChangeTime = getCurrentTime(host).getTime(); } // Update sourceFileInfo diff --git a/src/compiler/types.ts b/src/compiler/types.ts index cfe6b2c660b..1364aff8d5e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4026,6 +4026,7 @@ namespace ts { export interface WriteFileCallbackData { /*@internal*/ sourceMapUrlPos?: number; /*@internal*/ buildInfo?: BuildInfo; + /*@internal*/ diagnostics?: readonly DiagnosticWithLocation[]; } export type WriteFileCallback = ( fileName: string, @@ -4335,7 +4336,6 @@ namespace ts { diagnostics: readonly Diagnostic[]; emittedFiles?: string[]; // Array of files the compiler wrote to disk /* @internal */ sourceMaps?: SourceMapEmitResult[]; // Array of sourceMapData if compiler emitted sourcemaps - /* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit; } /* @internal */ diff --git a/src/server/project.ts b/src/server/project.ts index f3c881658f8..3ee83ea4c8c 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -709,7 +709,8 @@ namespace ts.server { this.program!, scriptInfo.path, this.cancellationToken, - maybeBind(this.projectService.host, this.projectService.host.createHash) + maybeBind(this.projectService.host, this.projectService.host.createHash), + this.getCanonicalFileName, ), sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined ); diff --git a/src/testRunner/unittests/services/languageService.ts b/src/testRunner/unittests/services/languageService.ts index c3f5f019541..b93215f4df2 100644 --- a/src/testRunner/unittests/services/languageService.ts +++ b/src/testRunner/unittests/services/languageService.ts @@ -62,7 +62,6 @@ export function Component(x: Config): any;` emitSkipped: true, diagnostics: emptyArray, outputFiles: emptyArray, - exportedModulesFromDeclarationEmit: undefined } ); @@ -80,7 +79,6 @@ export function Component(x: Config): any;` text: "export {};\r\n", writeByteOrderMark: false }], - exportedModulesFromDeclarationEmit: undefined } ); }); diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index 36aaf762141..de77465b505 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -524,5 +524,46 @@ console.log(a);`, modifyFs: fs => fs.writeFileSync("/src/project/constants.ts", "export default 2;"), }], }); + + function verifyModifierChange(declaration: boolean) { + verifyTscWithEdits({ + scenario: "incremental", + subScenario: `change to modifier of class expression field${declaration ? " with declaration emit enabled" : ""}`, + commandLineArgs: ["-p", "src/project", "--incremental"], + fs: () => loadProjectFromFiles({ + "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { declaration } }), + "/src/project/main.ts": Utils.dedent` + import MessageablePerson from './MessageablePerson.js'; + function logMessage( person: MessageablePerson ) { + console.log( person.message ); + }`, + "/src/project/MessageablePerson.ts": Utils.dedent` + const Messageable = () => { + return class MessageableClass { + public message = 'hello'; + } + }; + const wrapper = () => Messageable(); + type MessageablePerson = InstanceType>; + export default MessageablePerson;`, + }), + modifyFs: fs => appendText(fs, "/lib/lib.d.ts", Utils.dedent` + type ReturnType any> = T extends (...args: any) => infer R ? R : any; + type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;` + ), + edits: [ + { + subScenario: "modify public to protected", + modifyFs: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "public", "protected"), + }, + { + subScenario: "modify protected to public", + modifyFs: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "protected", "public"), + }, + ], + }); + } + verifyModifierChange(/*declaration*/ false); + verifyModifierChange(/*declaration*/ true); }); } diff --git a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts index 97132be83b7..8ea94a596c8 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts @@ -139,7 +139,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -175,7 +175,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -218,7 +218,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -261,7 +261,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -315,7 +315,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -369,7 +369,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -412,7 +412,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -455,7 +455,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -509,7 +509,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -563,7 +563,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -597,7 +597,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -628,7 +628,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -666,7 +666,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -704,7 +704,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -753,7 +753,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -802,7 +802,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -840,7 +840,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -878,7 +878,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -927,7 +927,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -976,7 +976,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1017,7 +1017,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -1053,7 +1053,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1107,7 +1107,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -1161,7 +1161,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1215,7 +1215,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -1269,7 +1269,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1323,7 +1323,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -1377,7 +1377,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1431,7 +1431,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path } }).response as EmitOutput; @@ -1485,7 +1485,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1519,7 +1519,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1568,7 +1568,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1617,7 +1617,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1666,7 +1666,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1715,7 +1715,7 @@ ${appendDts}` assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response as EmitOutput; @@ -1755,7 +1755,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -1791,7 +1791,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response as EmitOutput; @@ -1846,7 +1846,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -1900,7 +1900,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response as EmitOutput; @@ -1955,7 +1955,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -2009,7 +2009,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response as EmitOutput; @@ -2064,7 +2064,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -2118,7 +2118,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response as EmitOutput; @@ -2173,7 +2173,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } }).response as EmitOutput; @@ -2227,7 +2227,7 @@ ${appendDts}` } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + const actualEmitOutput = session.executeCommandSeq({ command: protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response as EmitOutput; diff --git a/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field-with-declaration-emit-enabled.js b/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field-with-declaration-emit-enabled.js new file mode 100644 index 00000000000..cea58e7453a --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field-with-declaration-emit-enabled.js @@ -0,0 +1,306 @@ +Input:: +//// [/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any; +type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any; + +//// [/src/project/main.ts] +import MessageablePerson from './MessageablePerson.js'; +function logMessage( person: MessageablePerson ) { + console.log( person.message ); +} + +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + public message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + +//// [/src/project/tsconfig.json] +{"compilerOptions":{"declaration":true}} + + + +Output:: +/lib/tsc -p src/project --incremental +exitCode:: ExitStatus.Success + + +//// [/src/project/main.d.ts] +export {}; + + +//// [/src/project/main.js] +"use strict"; +exports.__esModule = true; +function logMessage(person) { + console.log(person.message); +} + + +//// [/src/project/MessageablePerson.d.ts] +declare const wrapper: () => { + new (): { + message: string; + }; +}; +declare type MessageablePerson = InstanceType>; +export default MessageablePerson; + + +//// [/src/project/MessageablePerson.js] +"use strict"; +exports.__esModule = true; +var Messageable = function () { + return /** @class */ (function () { + function MessageableClass() { + this.message = 'hello'; + } + return MessageableClass; + }()); +}; +var wrapper = function () { return Messageable(); }; + + +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},{"version":"31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","signature":"-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n"},{"version":"4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}","signature":"-4882119183-export {};\r\n"}],"options":{"declaration":true},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,3,2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n" + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "-4882119183-export {};\r\n" + } + }, + "options": { + "declaration": true + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./main.ts", + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1693 +} + + + +Change:: modify public to protected +Input:: +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + protected message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + + + +Output:: +/lib/tsc -p src/project --incremental +src/project/main.ts:3:25 - error TS2445: Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses. + +3 console.log( person.message ); +   ~~~~~~~ + +src/project/MessageablePerson.ts:6:7 - error TS4094: Property 'message' of exported class expression may not be private or protected. + +6 const wrapper = () => Messageable(); +   ~~~~~~~ + + +Found 2 errors in 2 files. + +Errors Files + 1 src/project/main.ts:3 + 1 src/project/MessageablePerson.ts:6 +exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped + + +//// [/src/project/main.d.ts] file written with same contents +//// [/src/project/main.js] file written with same contents +//// [/src/project/MessageablePerson.js] file written with same contents +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},{"version":"3462418372-const Messageable = () => {\n return class MessageableClass {\n protected message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","signature":"-4323958125-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n(116,7)Error4094: Property 'message' of exported class expression may not be private or protected."},{"version":"4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}","signature":"-4882119183-export {};\r\n"}],"options":{"declaration":true},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[3,[{"file":"./main.ts","start":131,"length":7,"messageText":"Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses.","category":1,"code":2445}]],2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "3462418372-const Messageable = () => {\n return class MessageableClass {\n protected message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "-4323958125-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n(116,7)Error4094: Property 'message' of exported class expression may not be private or protected." + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "-4882119183-export {};\r\n" + } + }, + "options": { + "declaration": true + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + [ + "./main.ts", + [ + { + "file": "./main.ts", + "start": 131, + "length": 7, + "messageText": "Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses.", + "category": 1, + "code": 2445 + } + ] + ], + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1985 +} + + + +Change:: modify protected to public +Input:: +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + public message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + + + +Output:: +/lib/tsc -p src/project --incremental +exitCode:: ExitStatus.Success + + +//// [/src/project/main.d.ts] file written with same contents +//// [/src/project/main.js] file written with same contents +//// [/src/project/MessageablePerson.d.ts] file written with same contents +//// [/src/project/MessageablePerson.js] file written with same contents +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},{"version":"31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","signature":"-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n"},{"version":"4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}","signature":"-4882119183-export {};\r\n"}],"options":{"declaration":true},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,3,2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n" + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "-4882119183-export {};\r\n" + } + }, + "options": { + "declaration": true + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./main.ts", + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1693 +} + diff --git a/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field.js b/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field.js new file mode 100644 index 00000000000..922df600ea4 --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/change-to-modifier-of-class-expression-field.js @@ -0,0 +1,285 @@ +Input:: +//// [/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any; +type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any; + +//// [/src/project/main.ts] +import MessageablePerson from './MessageablePerson.js'; +function logMessage( person: MessageablePerson ) { + console.log( person.message ); +} + +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + public message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + +//// [/src/project/tsconfig.json] +{"compilerOptions":{"declaration":false}} + + + +Output:: +/lib/tsc -p src/project --incremental +exitCode:: ExitStatus.Success + + +//// [/src/project/main.js] +"use strict"; +exports.__esModule = true; +function logMessage(person) { + console.log(person.message); +} + + +//// [/src/project/MessageablePerson.js] +"use strict"; +exports.__esModule = true; +var Messageable = function () { + return /** @class */ (function () { + function MessageableClass() { + this.message = 'hello'; + } + return MessageableClass; + }()); +}; +var wrapper = function () { return Messageable(); }; + + +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},"31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}"],"options":{"declaration":false},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[[3,1]],"semanticDiagnosticsPerFile":[1,3,2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;" + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}" + } + }, + "options": { + "declaration": false + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./main.ts", + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1396 +} + + + +Change:: modify public to protected +Input:: +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + protected message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + + + +Output:: +/lib/tsc -p src/project --incremental +src/project/main.ts:3:25 - error TS2445: Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses. + +3 console.log( person.message ); +   ~~~~~~~ + + +Found 1 error in src/project/main.ts:3 + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + +//// [/src/project/main.js] file written with same contents +//// [/src/project/MessageablePerson.js] file written with same contents +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},{"version":"3462418372-const Messageable = () => {\n return class MessageableClass {\n protected message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","signature":"-4323958125-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n(116,7)Error4094: Property 'message' of exported class expression may not be private or protected."},{"version":"4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}","signature":"-4882119183-export {};\r\n"}],"options":{"declaration":false},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[3,[{"file":"./main.ts","start":131,"length":7,"messageText":"Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses.","category":1,"code":2445}]],2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "3462418372-const Messageable = () => {\n return class MessageableClass {\n protected message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "-4323958125-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n(116,7)Error4094: Property 'message' of exported class expression may not be private or protected." + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "-4882119183-export {};\r\n" + } + }, + "options": { + "declaration": false + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + [ + "./main.ts", + [ + { + "file": "./main.ts", + "start": 131, + "length": 7, + "messageText": "Property 'message' is protected and only accessible within class 'MessageableClass' and its subclasses.", + "category": 1, + "code": 2445 + } + ] + ], + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1986 +} + + + +Change:: modify protected to public +Input:: +//// [/src/project/MessageablePerson.ts] +const Messageable = () => { + return class MessageableClass { + public message = 'hello'; + } +}; +const wrapper = () => Messageable(); +type MessageablePerson = InstanceType>; +export default MessageablePerson; + + + +Output:: +/lib/tsc -p src/project --incremental +exitCode:: ExitStatus.Success + + +//// [/src/project/main.js] file written with same contents +//// [/src/project/MessageablePerson.js] file written with same contents +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./messageableperson.ts","./main.ts"],"fileInfos":[{"version":"5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;","affectsGlobalScope":true},{"version":"31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;","signature":"-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n"},{"version":"4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}","signature":"-4882119183-export {};\r\n"}],"options":{"declaration":false},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,3,2]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./messageableperson.ts", + "./main.ts" + ], + "fileNamesList": [ + [ + "./messageableperson.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "signature": "5700251342-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };type ReturnType any> = T extends (...args: any) => infer R ? R : any;\ntype InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any;", + "affectsGlobalScope": true + }, + "./messageableperson.ts": { + "version": "31173349369-const Messageable = () => {\n return class MessageableClass {\n public message = 'hello';\n }\n};\nconst wrapper = () => Messageable();\ntype MessageablePerson = InstanceType>;\nexport default MessageablePerson;", + "signature": "-13324779423-declare const wrapper: () => {\r\n new (): {\r\n message: string;\r\n };\r\n};\r\ndeclare type MessageablePerson = InstanceType>;\r\nexport default MessageablePerson;\r\n" + }, + "./main.ts": { + "version": "4191603667-import MessageablePerson from './MessageablePerson.js';\nfunction logMessage( person: MessageablePerson ) {\n console.log( person.message );\n}", + "signature": "-4882119183-export {};\r\n" + } + }, + "options": { + "declaration": false + }, + "referencedMap": { + "./main.ts": [ + "./messageableperson.ts" + ] + }, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./main.ts", + "./messageableperson.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1694 +} +