Skip to content

Commit ae0698d

Browse files
sheetalkamatjohnnyreilly
authored andcommitted
Fix SolutionBuilder watches (#1003)
* Fix simple run to start with * Try with --watch * More fixes * Tests for errors * Add back the deleted code * More changes to provide correct errors * Update file only if text is different from existing file text and handle watch * Update index.ts * Update index.ts * Remove error duplication in case of syntax errors * Add test for watch * tsbuildinfo files for referenced projects * Add alias loader so its easy to run from command line * Fix incorrect scheduling of the next build and fix copy for tests to write new files * Set tsbuildinfo as asset only if emitting the file from referenced project * Add support when the file is referenced indirectly from project * Support when referenced project is already built * Additional guidance for no emit when referenced file build is failed * Solution errors per module
1 parent bfa48c7 commit ae0698d

File tree

160 files changed

+7031
-343
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

160 files changed

+7031
-343
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
"scripts": {
88
"build": "tsc --version && tsc --project \"./src\"",
99
"lint": "tslint --project \"./src\"",
10-
"comparison-tests": "tsc --project \"./test/comparison-tests\" && npm link ./test/comparison-tests/testLib && node test/comparison-tests/run-tests.js",
11-
"comparison-tests-generate": "node test/comparison-tests/stub-new-version.js",
10+
"comparison-tests": "git clean -xfd test/comparison-tests && tsc --project \"./test/comparison-tests\" && npm link ./test/comparison-tests/testLib && node test/comparison-tests/run-tests.js",
11+
"comparison-tests-generate": "git clean -xfd test/comparison-tests && node test/comparison-tests/stub-new-version.js",
1212
"execution-tests": "git clean -xfd test/execution-tests && node test/execution-tests/run-tests.js",
13-
"test": "git clean -xfd test/execution-tests && node test/run-tests.js",
14-
"clean": "git clean -xfd test/execution-tests",
13+
"test": "git clean -xfd test/comparison-tests && git clean -xfd test/execution-tests && node test/run-tests.js",
14+
"clean": "git clean -xfd test/comparison-tests && git clean -xfd test/execution-tests",
1515
"docker:build": "docker build -t ts-loader .",
1616
"postdocker:build": "docker run -it ts-loader yarn test"
1717
},

src/after-compile.ts

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as ts from 'typescript';
33
import * as webpack from 'webpack';
44

55
import * as constants from './constants';
6-
import { getEmitOutput } from './instances';
6+
import { forEachResolvedProjectReference, getEmitOutput } from './instances';
77
import {
88
TSFile,
99
TSFiles,
@@ -68,6 +68,9 @@ export function makeAfterCompile(
6868
compilation
6969
);
7070

71+
provideSolutionErrorsToWebpack(compilation, modules, instance);
72+
provideTsBuildInfoFilesToWebpack(instance, compilation);
73+
7174
instance.filesWithErrors = filesWithErrors;
7275
instance.modifiedFiles = null;
7376
instance.projectsMissingSourceMaps = new Set();
@@ -195,7 +198,6 @@ function provideErrorsToWebpack(
195198
}
196199

197200
const sourceFile = program && program.getSourceFile(filePath);
198-
199201
// If the source file is undefined, that probably means it’s actually part of an unbuilt project reference,
200202
// which will have already produced a more useful error than the one we would get by proceeding here.
201203
// If it’s undefined and we’re not using project references at all, I guess carry on so the user will
@@ -256,6 +258,76 @@ function provideErrorsToWebpack(
256258
}
257259
}
258260

261+
function provideSolutionErrorsToWebpack(
262+
compilation: webpack.compilation.Compilation,
263+
modules: Map<string, WebpackModule[]>,
264+
instance: TSInstance
265+
) {
266+
if (
267+
!instance.solutionBuilderHost ||
268+
!(
269+
instance.solutionBuilderHost.diagnostics.global.length ||
270+
instance.solutionBuilderHost.diagnostics.perFile.size
271+
)
272+
) {
273+
return;
274+
}
275+
276+
const {
277+
compiler,
278+
loaderOptions,
279+
solutionBuilderHost: { diagnostics }
280+
} = instance;
281+
282+
for (const [filePath, perFileDiagnostics] of diagnostics.perFile) {
283+
// if we have access to a webpack module, use that
284+
const associatedModules = modules.get(filePath);
285+
if (associatedModules !== undefined) {
286+
associatedModules.forEach(module => {
287+
// remove any existing errors
288+
removeTSLoaderErrors(module.errors);
289+
290+
// append errors
291+
const formattedErrors = formatErrors(
292+
perFileDiagnostics,
293+
loaderOptions,
294+
instance.colors,
295+
compiler,
296+
{ module },
297+
compilation.compiler.context
298+
);
299+
300+
module.errors.push(...formattedErrors);
301+
compilation.errors.push(...formattedErrors);
302+
});
303+
} else {
304+
// otherwise it's a more generic error
305+
const formattedErrors = formatErrors(
306+
perFileDiagnostics,
307+
loaderOptions,
308+
instance.colors,
309+
compiler,
310+
{ file: filePath },
311+
compilation.compiler.context
312+
);
313+
314+
compilation.errors.push(...formattedErrors);
315+
}
316+
}
317+
318+
// Add global solution errors
319+
compilation.errors.push(
320+
...formatErrors(
321+
diagnostics.global,
322+
instance.loaderOptions,
323+
instance.colors,
324+
instance.compiler,
325+
{ file: 'tsconfig.json' },
326+
compilation.compiler.context
327+
)
328+
);
329+
}
330+
259331
/**
260332
* gather all declaration files from TypeScript and output them to webpack
261333
*/
@@ -287,6 +359,48 @@ function provideDeclarationFilesToWebpack(
287359
}
288360
}
289361

362+
/**
363+
* gather all .tsbuildinfo for the project
364+
*/
365+
function provideTsBuildInfoFilesToWebpack(
366+
instance: TSInstance,
367+
compilation: webpack.compilation.Compilation
368+
) {
369+
if (instance.solutionBuilderHost && instance.modifiedFiles) {
370+
const program = ensureProgram(instance);
371+
if (program) {
372+
forEachResolvedProjectReference(
373+
program.getResolvedProjectReferences(),
374+
resolvedRef => {
375+
if (
376+
resolvedRef.commandLine.fileNames.some(f =>
377+
instance.modifiedFiles!.has(path.resolve(f))
378+
)
379+
) {
380+
// TODO:: update compiler to expose this
381+
const buildInfoPath = (instance.compiler as any).getOutputPathForBuildInfo(
382+
resolvedRef.commandLine.options
383+
);
384+
if (buildInfoPath) {
385+
const text = instance.compiler.sys.readFile(buildInfoPath);
386+
if (text) {
387+
const assetPath = path.relative(
388+
compilation.compiler.outputPath,
389+
path.resolve(buildInfoPath)
390+
);
391+
compilation.assets[assetPath] = {
392+
source: () => text,
393+
size: () => text.length
394+
};
395+
}
396+
}
397+
}
398+
}
399+
);
400+
}
401+
}
402+
}
403+
290404
/**
291405
* handle all other errors. The basic approach here to get accurate error
292406
* reporting is to start with a "blank slate" each compilation and gather

0 commit comments

Comments
 (0)