Skip to content

Commit

Permalink
Merge pull request #701 from freeman/reportFiles
Browse files Browse the repository at this point in the history
Report diagnostics only on certain files [WIP]
  • Loading branch information
johnnyreilly committed Jan 20, 2018
2 parents 6d55769 + 92a73e2 commit ea8dfd7
Show file tree
Hide file tree
Showing 18 changed files with 662 additions and 19 deletions.
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -245,6 +245,21 @@ messages are emitted via webpack which is not affected by this flag.
You can squelch certain TypeScript errors by specifying an array of diagnostic
codes to ignore.

#### reportFiles *(string[]) (default=[])*

Only report errors on files matching these glob patterns.

```javascript
// in webpack.config.js
{
test: /\.ts$/,
loader: 'ts-loader',
options: { reportFiles: ['src/**/*.{ts,tsx}', '!src/skip.ts'] }
}
```

This can be useful when certain types definitions have errors that are not fatal to your application.

#### compiler *(string) (default='typescript')*

Allows use of TypeScript compilers other than the official one. Should be
Expand Down
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -39,9 +39,11 @@
"chalk": "^2.3.0",
"enhanced-resolve": "^3.0.0",
"loader-utils": "^1.0.2",
"micromatch": "^3.1.4",
"semver": "^5.0.1"
},
"devDependencies": {
"@types/micromatch": "^3.1.0",
"@types/semver": "^5.4.0",
"babel": "^6.0.0",
"babel-core": "^6.0.0",
Expand Down
11 changes: 8 additions & 3 deletions src/after-compile.ts
Expand Up @@ -68,7 +68,8 @@ function provideCompilerOptionDiagnosticErrorsToWebpack(
program.getOptionsDiagnostics() :
languageService!.getCompilerOptionsDiagnostics(),
loaderOptions, instance.colors, compiler,
{ file: configFilePath || 'tsconfig.json' }));
{ file: configFilePath || 'tsconfig.json' },
compilation.compiler.context));
}
}

Expand Down Expand Up @@ -162,13 +163,17 @@ function provideErrorsToWebpack(
removeTSLoaderErrors(module.errors);

// append errors
const formattedErrors = formatErrors(errors, loaderOptions, instance.colors, compiler, { module });
const formattedErrors = formatErrors(errors, loaderOptions,
instance.colors, compiler, { module },
compilation.compiler.context);
registerWebpackErrors(module.errors, formattedErrors);
registerWebpackErrors(compilation.errors, formattedErrors);
});
} else {
// otherwise it's a more generic error
registerWebpackErrors(compilation.errors, formatErrors(errors, loaderOptions, instance.colors, compiler, { file: filePath }));
registerWebpackErrors(compilation.errors, formatErrors(errors,
loaderOptions, instance.colors, compiler, { file: filePath },
compilation.compiler.context));
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/config.ts
Expand Up @@ -40,7 +40,8 @@ export function getConfigFile(
);

if (configFile.error !== undefined) {
configFileError = formatErrors([configFile.error], loaderOptions, colors, compiler, { file: configFilePath })[0];
configFileError = formatErrors([configFile.error], loaderOptions,
colors, compiler, { file: configFilePath }, loader.context)[0];
}
} else {
if (compilerCompatible) { log.logInfo(compilerDetailsLogMessage); }
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Expand Up @@ -111,7 +111,7 @@ function getLoaderOptions(loader: Webpack) {
}

type ValidLoaderOptions = keyof LoaderOptions;
const validLoaderOptions: ValidLoaderOptions[] = ['silent', 'logLevel', 'logInfoToStdOut', 'instance', 'compiler', 'contextAsConfigBasePath', 'configFile', 'transpileOnly', 'ignoreDiagnostics', 'errorFormatter', 'colors', 'compilerOptions', 'appendTsSuffixTo', 'appendTsxSuffixTo', 'entryFileCannotBeJs' /* DEPRECATED */, 'onlyCompileBundledFiles', 'happyPackMode', 'getCustomTransformers', 'experimentalWatchApi'];
const validLoaderOptions: ValidLoaderOptions[] = ['silent', 'logLevel', 'logInfoToStdOut', 'instance', 'compiler', 'contextAsConfigBasePath', 'configFile', 'transpileOnly', 'ignoreDiagnostics', 'errorFormatter', 'colors', 'compilerOptions', 'appendTsSuffixTo', 'appendTsxSuffixTo', 'entryFileCannotBeJs' /* DEPRECATED */, 'onlyCompileBundledFiles', 'happyPackMode', 'getCustomTransformers', 'reportFiles', 'experimentalWatchApi'];

/**
* Validate the supplied loader options.
Expand Down Expand Up @@ -149,6 +149,7 @@ function makeLoaderOptions(instanceName: string, configFileOptions: Partial<Load
happyPackMode: false,
colors: true,
onlyCompileBundledFiles: false,
reportFiles: [],
// When the watch API usage stabilises look to remove this option and make watch usage the default behaviour when available
experimentalWatchApi: false
} as Partial<LoaderOptions>, configFileOptions, loaderOptions);
Expand Down Expand Up @@ -273,7 +274,9 @@ function getTranspilationEmit(
if (!instance.loaderOptions.happyPackMode) {
registerWebpackErrors(
loader._module.errors,
formatErrors(diagnostics, instance.loaderOptions, instance.colors, instance.compiler, { module: loader._module })
formatErrors(diagnostics, instance.loaderOptions, instance.colors,
instance.compiler, { module: loader._module },
loader.context)
);
}

Expand Down
6 changes: 4 additions & 2 deletions src/instances.ts
Expand Up @@ -87,7 +87,8 @@ function successfulTypeScriptInstance(
const configParseResult = getConfigParseResult(compiler, configFile, basePath);

if (configParseResult.errors.length > 0 && !loaderOptions.happyPackMode) {
const errors = formatErrors(configParseResult.errors, loaderOptions, colors, compiler, { file: configFilePath });
const errors = formatErrors(configParseResult.errors, loaderOptions, colors,
compiler, { file: configFilePath }, loader.context);

registerWebpackErrors(loader._module.errors, errors);

Expand All @@ -110,7 +111,8 @@ function successfulTypeScriptInstance(
const diagnostics = program.getOptionsDiagnostics();
registerWebpackErrors(
loader._module.errors,
formatErrors(diagnostics, loaderOptions, colors, compiler!, {file: configFilePath || 'tsconfig.json'}));
formatErrors(diagnostics, loaderOptions, colors, compiler!,
{file: configFilePath || 'tsconfig.json'}, loader.context));
}

const instance: TSInstance = {
Expand Down
1 change: 1 addition & 0 deletions src/interfaces.ts
Expand Up @@ -282,6 +282,7 @@ export interface LoaderOptions {
contextAsConfigBasePath: boolean;
transpileOnly: boolean;
ignoreDiagnostics: number[];
reportFiles: string[];
errorFormatter: (message: ErrorInfo, colors: Chalk) => string;
onlyCompileBundledFiles: boolean;
colors: boolean;
Expand Down
18 changes: 16 additions & 2 deletions src/utils.ts
Expand Up @@ -2,6 +2,7 @@ import * as typescript from 'typescript';
import * as path from 'path';
import * as fs from 'fs';
import { Chalk } from 'chalk';
import * as micromatch from 'micromatch';

import constants = require('./constants');
import {
Expand Down Expand Up @@ -49,12 +50,25 @@ export function formatErrors(
loaderOptions: LoaderOptions,
colors: Chalk,
compiler: typeof typescript,
merge?: { file?: string; module?: WebpackModule }
merge: { file?: string; module?: WebpackModule },
context: string
): WebpackError[] {

return diagnostics
? diagnostics
.filter(diagnostic => loaderOptions.ignoreDiagnostics.indexOf(diagnostic.code) === -1)
.filter(diagnostic => {
if (loaderOptions.ignoreDiagnostics.indexOf(diagnostic.code) !== -1) {
return false;
}
if (loaderOptions.reportFiles.length > 0 && diagnostic.file) {
const relativeFileName = path.relative(context, diagnostic.file.fileName);
const matchResult = micromatch([relativeFileName], loaderOptions.reportFiles);
if (matchResult.length === 0) {
return false;
}
}
return true;
})
.map<WebpackError>(diagnostic => {
const file = diagnostic.file;
const position = file === undefined ? undefined : file.getLineAndCharacterOfPosition(diagnostic.start!);
Expand Down
3 changes: 3 additions & 0 deletions test/comparison-tests/reportFiles/app.ts
@@ -0,0 +1,3 @@
import './skip';
export let a: number
a = '10'
88 changes: 88 additions & 0 deletions test/comparison-tests/reportFiles/expectedOutput-2.6/bundle.js
@@ -0,0 +1,88 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

exports.__esModule = true;
__webpack_require__(1);
exports.a = '10';


/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

exports.__esModule = true;
exports.a = '10';


/***/ })
/******/ ]);
@@ -0,0 +1,4 @@
Asset Size Chunks Chunk Names
bundle.js 2.71 kB 0 [emitted] main
[0] ./.test/reportFiles/app.ts 78 bytes {0} [built]
[1] ./.test/reportFiles/skip.ts 59 bytes {0} [built]
@@ -0,0 +1,8 @@
Asset Size Chunks Chunk Names
bundle.js 2.71 kB 0 [emitted] main
[0] ./.test/reportFiles/app.ts 78 bytes {0} [built] [1 error]
[1] ./.test/reportFiles/skip.ts 59 bytes {0} [built]

ERROR in ./.test/reportFiles/app.ts
[tsl] ERROR in app.ts(3,1)
 TS2322: Type '"10"' is not assignable to type 'number'.
2 changes: 2 additions & 0 deletions test/comparison-tests/reportFiles/skip.ts
@@ -0,0 +1,2 @@
export let a: number
a = '10'
4 changes: 4 additions & 0 deletions test/comparison-tests/reportFiles/tsconfig.json
@@ -0,0 +1,4 @@
{
"compilerOptions": {
}
}
18 changes: 18 additions & 0 deletions test/comparison-tests/reportFiles/webpack.config.js
@@ -0,0 +1,18 @@
module.exports = {
entry: './app.ts',
output: {
filename: 'bundle.js'
},
resolve: {
extensions: ['.ts', 'tsx', '.js']
},
module: {
rules: [
{
test: /\.tsx?$/, loader: 'ts-loader', options: {
reportFiles: [ '**/*.ts', '!skip.ts' ]
}
}
]
}
}
Expand Up @@ -67,7 +67,7 @@
/* 0 */
/***/ (function(module, exports) {

throw new Error("Module build failed: Error: ts-loader was supplied with an unexpected loader option: notRealOption\n\nPlease take a look at the options you are supplying; the following are valid options:\nsilent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / compilerOptions / appendTsSuffixTo / appendTsxSuffixTo / entryFileCannotBeJs / onlyCompileBundledFiles / happyPackMode / getCustomTransformers\n\n at validateLoaderOptions (C:/source/ts-loader/dist/index.js:92:19)\n at getLoaderOptions (C:/source/ts-loader/dist/index.js:75:5)\n at Object.loader (C:/source/ts-loader/dist/index.js:23:19)");
throw new Error("Module build failed: Error: ts-loader was supplied with an unexpected loader option: notRealOption\n\nPlease take a look at the options you are supplying; the following are valid options:\nsilent / logLevel / logInfoToStdOut / instance / compiler / contextAsConfigBasePath / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / compilerOptions / appendTsSuffixTo / appendTsxSuffixTo / entryFileCannotBeJs / onlyCompileBundledFiles / happyPackMode / getCustomTransformers / reportFiles / experimentalWatchApi\n\n at validateLoaderOptions (C:/source/ts-loader/dist/index.js:92:19)\n at getLoaderOptions (C:/source/ts-loader/dist/index.js:75:5)\n at Object.loader (C:/source/ts-loader/dist/index.js:23:19)");

/***/ })
/******/ ]);
Expand Up @@ -6,7 +6,7 @@ ERROR in ./.test/validateLoaderOptionNames/app.ts
Module build failed: Error: ts-loader was supplied with an unexpected loader option: notRealOption

Please take a look at the options you are supplying; the following are valid options:
silent / logLevel / logInfoToStdOut / instance / compiler / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / compilerOptions / appendTsSuffixTo / appendTsxSuffixTo / entryFileCannotBeJs / onlyCompileBundledFiles / happyPackMode / getCustomTransformers
silent / logLevel / logInfoToStdOut / instance / compiler / contextAsConfigBasePath / configFile / transpileOnly / ignoreDiagnostics / errorFormatter / colors / compilerOptions / appendTsSuffixTo / appendTsxSuffixTo / entryFileCannotBeJs / onlyCompileBundledFiles / happyPackMode / getCustomTransformers / reportFiles / experimentalWatchApi

at validateLoaderOptions (dist\index.js:92:19)
at getLoaderOptions (dist\index.js:75:5)
Expand Down

0 comments on commit ea8dfd7

Please sign in to comment.