Skip to content

Commit f506b28

Browse files
committed
Mark the declarations visible correctly when emit is disabled but asked to emit declarations for watch mode
Fixes microsoft#25068
1 parent 1c3259d commit f506b28

5 files changed

Lines changed: 76 additions & 3 deletions

File tree

src/compiler/emitter.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ namespace ts {
192192
// Setup and perform the transformation to retrieve declarations from the input files
193193
const nonJsFiles = filter(sourceFiles, isSourceFileNotJavaScript);
194194
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles;
195+
if (emitOnlyDtsFiles && !compilerOptions.declaration) {
196+
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
197+
// Do that here when emitting only dts files
198+
nonJsFiles.forEach(collectLinkedAliases);
199+
}
195200
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, concatenate([transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false);
196201
if (length(declarationTransform.diagnostics)) {
197202
for (const diagnostic of declarationTransform.diagnostics!) {
@@ -221,6 +226,20 @@ namespace ts {
221226
declarationTransform.dispose();
222227
}
223228

229+
function collectLinkedAliases(node: Node) {
230+
if (isExportAssignment(node)) {
231+
if (node.expression.kind === SyntaxKind.Identifier) {
232+
resolver.collectLinkedAliases(node.expression as Identifier, /*setVisibility*/ true);
233+
}
234+
return;
235+
}
236+
else if (isExportSpecifier(node)) {
237+
resolver.collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true);
238+
return;
239+
}
240+
forEachChild(node, collectLinkedAliases);
241+
}
242+
224243
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapRecorder: SourceMapWriter) {
225244
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined;
226245
const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined;

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3331,7 +3331,7 @@ namespace ts {
33313331
getNodeCheckFlags(node: Node): NodeCheckFlags;
33323332
isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean;
33333333
isLateBound(node: Declaration): node is LateBoundDeclaration;
3334-
collectLinkedAliases(node: Identifier): Node[] | undefined;
3334+
collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined;
33353335
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
33363336
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
33373337
isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean;

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,9 @@ interface Array<T> {}`
571571
}
572572

573573
private addFileOrFolderInFolder(folder: FsFolder, fileOrDirectory: FsFile | FsFolder | FsSymLink, ignoreWatch?: boolean) {
574-
insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path)));
574+
if (!this.fs.has(fileOrDirectory.path)) {
575+
insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path)));
576+
}
575577
folder.modifiedTime = this.now();
576578
this.fs.set(fileOrDirectory.path, fileOrDirectory);
577579

src/testRunner/unittests/tscWatchMode.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,58 @@ namespace ts.tscWatch {
12181218
checkWatchedFiles(host, files.map(f => f.path));
12191219
}
12201220
});
1221+
1222+
it("updates errors correctly when declaration emit is disabled in compiler options", () => {
1223+
const currentDirectory = "/user/username/projects/myproject";
1224+
const aFile: File = {
1225+
path: `${currentDirectory}/a.ts`,
1226+
content: `import test from './b';
1227+
test(4, 5);`
1228+
};
1229+
const bFileContent = `function test(x: number, y: number) {
1230+
return x + y / 5;
1231+
}
1232+
export default test;`;
1233+
const bFile: File = {
1234+
path: `${currentDirectory}/b.ts`,
1235+
content: bFileContent
1236+
};
1237+
const tsconfigFile: File = {
1238+
path: `${currentDirectory}/tsconfig.json`,
1239+
content: JSON.stringify({
1240+
compilerOptions: {
1241+
module: "commonjs",
1242+
noEmit: true,
1243+
strict: true,
1244+
}
1245+
})
1246+
};
1247+
const files = [aFile, bFile, libFile, tsconfigFile];
1248+
const host = createWatchedSystem(files, { currentDirectory });
1249+
const watch = createWatchOfConfigFile("tsconfig.json", host);
1250+
checkOutputErrorsInitial(host, emptyArray);
1251+
1252+
changeParameterType("x", "string", [
1253+
getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.indexOf("4"), 1, Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1, "4", "string")
1254+
]);
1255+
changeParameterType("y", "string", [
1256+
getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.indexOf("5"), 1, Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1, "5", "string"),
1257+
getDiagnosticOfFileFromProgram(watch(), bFile.path, bFile.content.indexOf("y /"), 1, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type)
1258+
]);
1259+
1260+
function changeParameterType(parameterName: string, toType: string, expectedErrors: ReadonlyArray<Diagnostic>) {
1261+
const newContent = bFileContent.replace(new RegExp(`${parameterName}\: [a-z]*`), `${parameterName}: ${toType}`);
1262+
1263+
verifyErrorsWithBFileContents(newContent, expectedErrors);
1264+
verifyErrorsWithBFileContents(bFileContent, emptyArray);
1265+
}
1266+
1267+
function verifyErrorsWithBFileContents(content: string, expectedErrors: ReadonlyArray<Diagnostic>) {
1268+
host.writeFile(bFile.path, content);
1269+
host.runQueuedTimeoutCallbacks();
1270+
checkOutputErrorsIncremental(host, expectedErrors);
1271+
}
1272+
});
12211273
});
12221274

12231275
describe("tsc-watch emit with outFile or out setting", () => {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2915,7 +2915,7 @@ declare namespace ts {
29152915
getNodeCheckFlags(node: Node): NodeCheckFlags;
29162916
isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean;
29172917
isLateBound(node: Declaration): node is LateBoundDeclaration;
2918-
collectLinkedAliases(node: Identifier): Node[] | undefined;
2918+
collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined;
29192919
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
29202920
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
29212921
isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean;

0 commit comments

Comments
 (0)