Skip to content

feat: migrate from reporters to workers #691

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*.log

# Package artifacts
lib
/lib

# Package archive used by e2e tests
fork-ts-checker-webpack-plugin-0.0.0-semantic-release.tgz
Expand Down
33 changes: 19 additions & 14 deletions src/ForkTsCheckerWebpackPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as path from 'path';

import { cosmiconfigSync } from 'cosmiconfig';
import merge from 'deepmerge';
import type { JSONSchema7 } from 'json-schema';
Expand All @@ -15,10 +17,12 @@ import { dependenciesPool, issuesPool } from './hooks/pluginPools';
import { tapAfterCompileToAddDependencies } from './hooks/tapAfterCompileToAddDependencies';
import { tapAfterEnvironmentToPatchWatching } from './hooks/tapAfterEnvironmentToPatchWatching';
import { tapErrorToLogMessage } from './hooks/tapErrorToLogMessage';
import { tapStartToConnectAndRunReporter } from './hooks/tapStartToConnectAndRunReporter';
import { tapStopToDisconnectReporter } from './hooks/tapStopToDisconnectReporter';
import { createTypeScriptReporterRpcClient } from './typescript-reporter/reporter/TypeScriptReporterRpcClient';
import { assertTypeScriptSupport } from './typescript-reporter/TypeScriptSupport';
import { tapStartToRunWorkers } from './hooks/tapStartToRunWorkers';
import { tapStopToTerminateWorkers } from './hooks/tapStopToTerminateWorkers';
import { assertTypeScriptSupport } from './typescript/TypeScriptSupport';
import type { GetDependenciesWorker } from './typescript/worker/get-dependencies-worker';
import type { GetIssuesWorker } from './typescript/worker/get-issues-worker';
import { createRpcWorker } from './utils/rpc';

class ForkTsCheckerWebpackPlugin {
/**
Expand Down Expand Up @@ -61,19 +65,20 @@ class ForkTsCheckerWebpackPlugin {
const state = createForkTsCheckerWebpackPluginState();

assertTypeScriptSupport(configuration.typescript);
const issuesReporter = createTypeScriptReporterRpcClient(configuration.typescript);
const dependenciesReporter = createTypeScriptReporterRpcClient(configuration.typescript);
const getIssuesWorker = createRpcWorker<GetIssuesWorker>(
path.resolve(__dirname, './typescript/worker/get-issues-worker.js'),
configuration.typescript,
configuration.typescript.memoryLimit
);
const getDependenciesWorker = createRpcWorker<GetDependenciesWorker>(
path.resolve(__dirname, './typescript/worker/get-dependencies-worker.js'),
configuration.typescript
);

tapAfterEnvironmentToPatchWatching(compiler, state);
tapStartToConnectAndRunReporter(
compiler,
issuesReporter,
dependenciesReporter,
configuration,
state
);
tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, configuration, state);
tapAfterCompileToAddDependencies(compiler, configuration, state);
tapStopToDisconnectReporter(compiler, issuesReporter, dependenciesReporter, state);
tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state);
tapErrorToLogMessage(compiler, configuration);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/ForkTsCheckerWebpackPluginConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { IssueConfiguration } from './issue/IssueConfiguration';
import { createIssueConfiguration } from './issue/IssueConfiguration';
import type { LoggerConfiguration } from './logger/LoggerConfiguration';
import { createLoggerConfiguration } from './logger/LoggerConfiguration';
import type { TypeScriptReporterConfiguration } from './typescript-reporter/TypeScriptReporterConfiguration';
import { createTypeScriptReporterConfiguration } from './typescript-reporter/TypeScriptReporterConfiguration';
import type { TypeScriptReporterConfiguration } from './typescript/TypeScriptReporterConfiguration';
import { createTypeScriptReporterConfiguration } from './typescript/TypeScriptReporterConfiguration';

interface ForkTsCheckerWebpackPluginConfiguration {
async: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/ForkTsCheckerWebpackPluginOptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FormatterOptions } from './formatter';
import type { IssueOptions } from './issue/IssueOptions';
import type LoggerOptions from './logger/LoggerOptions';
import type { TypeScriptReporterOptions } from './typescript-reporter/TypeScriptReporterOptions';
import type { TypeScriptReporterOptions } from './typescript/TypeScriptReporterOptions';

interface ForkTsCheckerWebpackPluginOptions {
async?: boolean;
Expand Down
8 changes: 3 additions & 5 deletions src/ForkTsCheckerWebpackPluginState.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import type { FullTap } from 'tapable';

import type { FilesMatch } from './files-match';
import type { Issue } from './issue';
import type { FilesMatch, Report } from './reporter';

interface ForkTsCheckerWebpackPluginState {
issuesReportPromise: Promise<Report | undefined>;
dependenciesReportPromise: Promise<Report | undefined>;
issuesPromise: Promise<Issue[] | undefined>;
dependenciesPromise: Promise<FilesMatch | undefined>;
lastDependencies: FilesMatch | undefined;
watching: boolean;
initialized: boolean;
iteration: number;
webpackDevServerDoneTap: FullTap | undefined;
}

function createForkTsCheckerWebpackPluginState(): ForkTsCheckerWebpackPluginState {
return {
issuesReportPromise: Promise.resolve(undefined),
dependenciesReportPromise: Promise.resolve(undefined),
issuesPromise: Promise.resolve(undefined),
dependenciesPromise: Promise.resolve(undefined),
lastDependencies: undefined,
watching: false,
initialized: false,
iteration: 0,
webpackDevServerDoneTap: undefined,
};
}
Expand Down
5 changes: 0 additions & 5 deletions src/error/OperationCanceledError.ts

This file was deleted.

14 changes: 7 additions & 7 deletions src/reporter/FilesChange.ts → src/files-change.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import type { Compiler } from 'webpack';
import type * as webpack from 'webpack';

import subtract from '../utils/array/substract';
import unique from '../utils/array/unique';
import subtract from './utils/array/substract';
import unique from './utils/array/unique';

interface FilesChange {
changedFiles?: string[];
deletedFiles?: string[];
}

const compilerFilesChangeMap = new WeakMap<Compiler, FilesChange>();
const compilerFilesChangeMap = new WeakMap<webpack.Compiler, FilesChange>();

function getFilesChange(compiler: Compiler): FilesChange {
function getFilesChange(compiler: webpack.Compiler): FilesChange {
return compilerFilesChangeMap.get(compiler) || { changedFiles: [], deletedFiles: [] };
}

function updateFilesChange(compiler: Compiler, change: FilesChange): void {
function updateFilesChange(compiler: webpack.Compiler, change: FilesChange): void {
compilerFilesChangeMap.set(compiler, aggregateFilesChanges([getFilesChange(compiler), change]));
}

function clearFilesChange(compiler: Compiler): void {
function clearFilesChange(compiler: webpack.Compiler): void {
compilerFilesChangeMap.delete(compiler);
}

Expand Down
File renamed without changes.
4 changes: 4 additions & 0 deletions src/hooks/interceptDoneToGetWebpackDevServerTap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';

function interceptDoneToGetWebpackDevServerTap(
compiler: webpack.Compiler,
configuration: ForkTsCheckerWebpackPluginConfiguration,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

// inspired by https://github.com/ypresto/fork-ts-checker-async-overlay-webpack-plugin
compiler.hooks.done.intercept({
register: (tap) => {
Expand All @@ -16,6 +19,7 @@ function interceptDoneToGetWebpackDevServerTap(
tap.type === 'sync' &&
configuration.logger.devServer
) {
debug('Intercepting webpack-dev-server tap.');
state.webpackDevServerDoneTap = tap;
}
return tap;
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/pluginHooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { SyncHook, SyncWaterfallHook, AsyncSeriesWaterfallHook } from 'tapable';
import type * as webpack from 'webpack';

import type { FilesChange } from '../files-change';
import type { Issue } from '../issue';
import type { FilesChange } from '../reporter';

const compilerHookMap = new WeakMap<
webpack.Compiler | webpack.MultiCompiler,
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/tapAfterCompileToAddDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';

function tapAfterCompileToAddDependencies(
compiler: webpack.Compiler,
configuration: ForkTsCheckerWebpackPluginConfiguration,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', async (compilation) => {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
Expand All @@ -16,6 +19,7 @@ function tapAfterCompileToAddDependencies(

const dependencies = await state.dependenciesPromise;

debug(`Got dependencies from the getDependenciesWorker.`, dependencies);
if (dependencies) {
state.lastDependencies = dependencies;

Expand Down
4 changes: 4 additions & 0 deletions src/hooks/tapAfterCompileToGetIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';
import type { Issue } from '../issue';
import { IssueWebpackError } from '../issue/IssueWebpackError';

Expand All @@ -13,6 +14,7 @@ function tapAfterCompileToGetIssues(
state: ForkTsCheckerWebpackPluginState
) {
const hooks = getForkTsCheckerWebpackPluginHooks(compiler);
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', async (compilation) => {
if (compilation.compiler !== compiler) {
Expand All @@ -29,6 +31,8 @@ function tapAfterCompileToGetIssues(
return;
}

debug('Got issues from getIssuesWorker.', issues?.length);

if (!issues) {
// some error has been thrown or it was canceled
return;
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/tapAfterEnvironmentToPatchWatching.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';
import { InclusiveNodeWatchFileSystem } from '../watch/InclusiveNodeWatchFileSystem';
import type { WatchFileSystem } from '../watch/WatchFileSystem';

function tapAfterEnvironmentToPatchWatching(
compiler: webpack.Compiler,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterEnvironment.tap('ForkTsCheckerWebpackPlugin', () => {
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
debug("Overwriting webpack's watch file system.");
// wrap original watch file system
compiler.watchFileSystem = new InclusiveNodeWatchFileSystem(
// we use some internals here
watchFileSystem as WatchFileSystem,
compiler,
state
);
} else {
debug('No watch file system found - plugin may not work correctly.');
}
});
}
Expand Down
14 changes: 5 additions & 9 deletions src/hooks/tapDoneToAsyncGetIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { createWebpackFormatter } from '../formatter/WebpackFormatter';
import { getInfrastructureLogger } from '../infrastructure-logger';
import type { Issue } from '../issue';
import { IssueWebpackError } from '../issue/IssueWebpackError';
import isPending from '../utils/async/isPending';
Expand All @@ -17,14 +18,14 @@ function tapDoneToAsyncGetIssues(
state: ForkTsCheckerWebpackPluginState
) {
const hooks = getForkTsCheckerWebpackPluginHooks(compiler);
const { log, debug } = getInfrastructureLogger(compiler);

compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', async (stats) => {
if (stats.compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}

const reportPromise = state.issuesReportPromise;
const issuesPromise = state.issuesPromise;
let issues: Issue[] | undefined;

Expand All @@ -38,6 +39,7 @@ function tapDoneToAsyncGetIssues(
}

issues = await issuesPromise;
debug('Got issues from getIssuesWorker.', issues?.length);
} catch (error) {
hooks.error.call(error, stats.compilation);
return;
Expand All @@ -48,11 +50,6 @@ function tapDoneToAsyncGetIssues(
return;
}

if (reportPromise !== state.issuesReportPromise) {
// there is a newer report - ignore this one
return;
}

// filter list of issues by provided issue predicate
issues = issues.filter(configuration.issue.predicate);

Expand Down Expand Up @@ -81,13 +78,12 @@ function tapDoneToAsyncGetIssues(
}
});

debug('Sending issues to the webpack-dev-server.');
state.webpackDevServerDoneTap.fn(stats);
}

if (stats.startTime) {
configuration.logger.infrastructure.log(
`Time: ${Math.round(Date.now() - stats.startTime).toString()} ms`
);
log(`Time: ${Math.round(Date.now() - stats.startTime).toString()} ms`);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/tapErrorToLogMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import chalk from 'chalk';
import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import { RpcIpcMessagePortClosedError } from '../rpc/rpc-ipc/error/RpcIpcMessagePortClosedError';
import { RpcExitError } from '../utils/rpc';

import { getForkTsCheckerWebpackPluginHooks } from './pluginHooks';

Expand All @@ -15,7 +15,7 @@ function tapErrorToLogMessage(
hooks.error.tap('ForkTsCheckerWebpackPlugin', (error) => {
configuration.logger.issues.error(String(error));

if (error instanceof RpcIpcMessagePortClosedError) {
if (error instanceof RpcExitError) {
if (error.signal === 'SIGINT') {
configuration.logger.issues.error(
chalk.red(
Expand Down
Loading