Skip to content

Commit

Permalink
Fix handling of noEmit/emitDeclarationOnly in watch mode
Browse files Browse the repository at this point in the history
Closes #1716 (again)
  • Loading branch information
Gerrit0 committed Oct 16, 2021
1 parent fbf198e commit 68d5cbd
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 16 deletions.
56 changes: 43 additions & 13 deletions src/lib/application.ts
Expand Up @@ -13,6 +13,7 @@ import {
writeFile,
discoverNpmPlugins,
NeverIfInternal,
TSConfigReader,
} from "./utils/index";

import {
Expand All @@ -23,13 +24,13 @@ import {
import { Options, BindOption } from "./utils";
import type { TypeDocOptions } from "./utils/options/declaration";
import { flatMap, unique } from "./utils/array";
import { basename } from "path";
import { validateExports } from "./validation/exports";
import { ok } from "assert";
import {
DocumentationEntryPoint,
EntryPointStrategy,
getEntryPoints,
getWatchEntryPoints,
} from "./utils/entry-point";
import { nicePath } from "./utils/paths";

Expand Down Expand Up @@ -297,24 +298,17 @@ export class Application extends ChildableComponent<
return;
}

// Matches the behavior of the tsconfig option reader.
let tsconfigFile = this.options.getValue("tsconfig");
tsconfigFile =
ts.findConfigFile(
tsconfigFile,
ts.sys.fileExists,
tsconfigFile.toLowerCase().endsWith(".json")
? basename(tsconfigFile)
: undefined
) ?? "tsconfig.json";
const tsconfigFile =
TSConfigReader.findConfigFile(this.options.getValue("tsconfig")) ??
"tsconfig.json";

// We don't want to do it the first time to preserve initial debug status messages. They'll be lost
// after the user saves a file, but better than nothing...
let firstStatusReport = true;

const host = ts.createWatchCompilerHost(
tsconfigFile,
this.options.fixCompilerOptions({}),
{},
ts.sys,
ts.createEmitAndSemanticDiagnosticsBuilderProgram,
(diagnostic) => this.logger.diagnostic(diagnostic),
Expand Down Expand Up @@ -343,8 +337,20 @@ export class Application extends ChildableComponent<
}

if (successFinished) {
if (
this.options.getValue("emit") === "both" ||
this.options.getValue("emit") === true
) {
currentProgram.emit();
}

this.logger.resetErrors();
const entryPoints = this.getEntryPoints();
this.logger.resetWarnings();
const entryPoints = getWatchEntryPoints(
this.logger,
this.options,
currentProgram
);
if (!entryPoints) {
return;
}
Expand All @@ -358,6 +364,30 @@ export class Application extends ChildableComponent<
}
};

const origCreateProgram = host.createProgram;
host.createProgram = (
rootNames,
options,
host,
oldProgram,
configDiagnostics,
references
) => {
// If we always do this, we'll get a crash the second time a program is created.
if (rootNames !== undefined) {
options = this.options.fixCompilerOptions(options || {});
}

return origCreateProgram(
rootNames,
options,
host,
oldProgram,
configDiagnostics,
references
);
};

const origAfterProgramCreate = host.afterProgramCreate;
host.afterProgramCreate = (program) => {
if (ts.getPreEmitDiagnostics(program.getProgram()).length === 0) {
Expand Down
39 changes: 39 additions & 0 deletions src/lib/utils/entry-point.ts
Expand Up @@ -78,6 +78,45 @@ export function getEntryPoints(
return result;
}

export function getWatchEntryPoints(
logger: Logger,
options: Options,
program: ts.Program
): DocumentationEntryPoint[] | undefined {
let result: DocumentationEntryPoint[] | undefined;

const entryPoints = options.getValue("entryPoints");
switch (options.getValue("entryPointStrategy")) {
case EntryPointStrategy.Resolve:
result = getEntryPointsForPaths(logger, entryPoints, options, [
program,
]);
break;

case EntryPointStrategy.Expand:
result = getExpandedEntryPointsForPaths(
logger,
entryPoints,
options,
[program]
);
break;

case EntryPointStrategy.Packages:
logger.error(
"Watch mode does not support 'packages' style entry points."
);
break;
}

if (result && result.length === 0) {
logger.error("Unable to find any entry points.");
return;
}

return result;
}

function getModuleName(fileName: string, baseDir: string) {
return normalizePath(relative(baseDir, fileName)).replace(
/(\/index)?(\.d)?\.[tj]sx?$/,
Expand Down
20 changes: 17 additions & 3 deletions src/lib/utils/options/readers/tsconfig.ts
Expand Up @@ -24,15 +24,29 @@ export class TSConfigReader implements OptionsReader {

name = "tsconfig-json";

read(container: Options, logger: Logger): void {
const file = container.getValue("tsconfig");

/**
* Not considered part of the public API. You can use it, but it might break.
* @internal
*/
static findConfigFile(file: string): string | undefined {
let fileToRead: string | undefined = file;
if (isDir(fileToRead)) {
fileToRead = ts.findConfigFile(file, isFile);
}

if (!fileToRead || !isFile(fileToRead)) {
return;
}

return fileToRead;
}

read(container: Options, logger: Logger): void {
const file = container.getValue("tsconfig");

let fileToRead = TSConfigReader.findConfigFile(file);

if (!fileToRead) {
// If the user didn't give us this option, we shouldn't complain about not being able to find it.
if (container.isSet("tsconfig")) {
logger.error(`The tsconfig file ${file} does not exist`);
Expand Down

0 comments on commit 68d5cbd

Please sign in to comment.