Skip to content

Commit

Permalink
Fix SolutionBuilder watches (#1003)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
sheetalkamat authored and johnnyreilly committed Sep 19, 2019
1 parent bfa48c7 commit ae0698d
Show file tree
Hide file tree
Showing 160 changed files with 7,031 additions and 343 deletions.
8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -7,11 +7,11 @@
"scripts": {
"build": "tsc --version && tsc --project \"./src\"",
"lint": "tslint --project \"./src\"",
"comparison-tests": "tsc --project \"./test/comparison-tests\" && npm link ./test/comparison-tests/testLib && node test/comparison-tests/run-tests.js",
"comparison-tests-generate": "node test/comparison-tests/stub-new-version.js",
"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",
"comparison-tests-generate": "git clean -xfd test/comparison-tests && node test/comparison-tests/stub-new-version.js",
"execution-tests": "git clean -xfd test/execution-tests && node test/execution-tests/run-tests.js",
"test": "git clean -xfd test/execution-tests && node test/run-tests.js",
"clean": "git clean -xfd test/execution-tests",
"test": "git clean -xfd test/comparison-tests && git clean -xfd test/execution-tests && node test/run-tests.js",
"clean": "git clean -xfd test/comparison-tests && git clean -xfd test/execution-tests",
"docker:build": "docker build -t ts-loader .",
"postdocker:build": "docker run -it ts-loader yarn test"
},
Expand Down
118 changes: 116 additions & 2 deletions src/after-compile.ts
Expand Up @@ -3,7 +3,7 @@ import * as ts from 'typescript';
import * as webpack from 'webpack';

import * as constants from './constants';
import { getEmitOutput } from './instances';
import { forEachResolvedProjectReference, getEmitOutput } from './instances';
import {
TSFile,
TSFiles,
Expand Down Expand Up @@ -68,6 +68,9 @@ export function makeAfterCompile(
compilation
);

provideSolutionErrorsToWebpack(compilation, modules, instance);
provideTsBuildInfoFilesToWebpack(instance, compilation);

instance.filesWithErrors = filesWithErrors;
instance.modifiedFiles = null;
instance.projectsMissingSourceMaps = new Set();
Expand Down Expand Up @@ -195,7 +198,6 @@ function provideErrorsToWebpack(
}

const sourceFile = program && program.getSourceFile(filePath);

// If the source file is undefined, that probably means it’s actually part of an unbuilt project reference,
// which will have already produced a more useful error than the one we would get by proceeding here.
// If it’s undefined and we’re not using project references at all, I guess carry on so the user will
Expand Down Expand Up @@ -256,6 +258,76 @@ function provideErrorsToWebpack(
}
}

function provideSolutionErrorsToWebpack(
compilation: webpack.compilation.Compilation,
modules: Map<string, WebpackModule[]>,
instance: TSInstance
) {
if (
!instance.solutionBuilderHost ||
!(
instance.solutionBuilderHost.diagnostics.global.length ||
instance.solutionBuilderHost.diagnostics.perFile.size
)
) {
return;
}

const {
compiler,
loaderOptions,
solutionBuilderHost: { diagnostics }
} = instance;

for (const [filePath, perFileDiagnostics] of diagnostics.perFile) {
// if we have access to a webpack module, use that
const associatedModules = modules.get(filePath);
if (associatedModules !== undefined) {
associatedModules.forEach(module => {
// remove any existing errors
removeTSLoaderErrors(module.errors);

// append errors
const formattedErrors = formatErrors(
perFileDiagnostics,
loaderOptions,
instance.colors,
compiler,
{ module },
compilation.compiler.context
);

module.errors.push(...formattedErrors);
compilation.errors.push(...formattedErrors);
});
} else {
// otherwise it's a more generic error
const formattedErrors = formatErrors(
perFileDiagnostics,
loaderOptions,
instance.colors,
compiler,
{ file: filePath },
compilation.compiler.context
);

compilation.errors.push(...formattedErrors);
}
}

// Add global solution errors
compilation.errors.push(
...formatErrors(
diagnostics.global,
instance.loaderOptions,
instance.colors,
instance.compiler,
{ file: 'tsconfig.json' },
compilation.compiler.context
)
);
}

/**
* gather all declaration files from TypeScript and output them to webpack
*/
Expand Down Expand Up @@ -287,6 +359,48 @@ function provideDeclarationFilesToWebpack(
}
}

/**
* gather all .tsbuildinfo for the project
*/
function provideTsBuildInfoFilesToWebpack(
instance: TSInstance,
compilation: webpack.compilation.Compilation
) {
if (instance.solutionBuilderHost && instance.modifiedFiles) {
const program = ensureProgram(instance);
if (program) {
forEachResolvedProjectReference(
program.getResolvedProjectReferences(),
resolvedRef => {
if (
resolvedRef.commandLine.fileNames.some(f =>
instance.modifiedFiles!.has(path.resolve(f))
)
) {
// TODO:: update compiler to expose this
const buildInfoPath = (instance.compiler as any).getOutputPathForBuildInfo(
resolvedRef.commandLine.options
);
if (buildInfoPath) {
const text = instance.compiler.sys.readFile(buildInfoPath);
if (text) {
const assetPath = path.relative(
compilation.compiler.outputPath,
path.resolve(buildInfoPath)
);
compilation.assets[assetPath] = {
source: () => text,
size: () => text.length
};
}
}
}
}
);
}
}
}

/**
* handle all other errors. The basic approach here to get accurate error
* reporting is to start with a "blank slate" each compilation and gather
Expand Down

0 comments on commit ae0698d

Please sign in to comment.