diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4f4182b..587aa9a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## v0.4.14
+
+* [Add support for `reportFiles` option](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/179) (#179)
+
+## v0.4.13
+
+* [Merge in `compilerOptions` prior to calling `parseJsonConfigFileContent`](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/176) (#176)
+
+## v0.4.12
+
+* [Add `compilerOptions` option](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/173) (#173)
+
+## v0.4.11
+
+* [Fix os.cpus is not a function](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/172) (#172)
+
## v0.4.10
* [Allow fork-ts-checker-webpack-plugin to be imported in .ts files using ESM import syntax](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/163) (#163)
diff --git a/README.md b/README.md
index 202f2ee2..e218c039 100644
--- a/README.md
+++ b/README.md
@@ -1,240 +1 @@
-# Fork TS Checker Webpack Plugin
-[](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin)
-[](https://travis-ci.org/Realytics/fork-ts-checker-webpack-plugin)
-
-Webpack plugin that runs typescript type checker on a separate process.
-
-## Installation
-This plugin requires minimum **webpack 2.3**, **typescript 2.1** and optionally **tslint 4.0**
-```sh
-npm install --save-dev fork-ts-checker-webpack-plugin
-```
-Basic webpack config (with [ts-loader](https://github.com/TypeStrong/ts-loader))
-```js
-var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
-
-var webpackConfig = {
- context: __dirname, // to automatically find tsconfig.json
- entry: './src/index.ts',
- module: {
- rules: [
- {
- test: /\.tsx?$/,
- loader: 'ts-loader',
- options: {
- // disable type checker - we will use it in fork plugin
- transpileOnly: true
- }
- }
- ]
- },
- plugins: [
- new ForkTsCheckerWebpackPlugin()
- ]
-};
-```
-
-## Motivation
-There is already similar solution - [awesome-typescript-loader](https://github.com/s-panferov/awesome-typescript-loader). You can
-add `CheckerPlugin` and delegate checker to the separate process. The problem with `awesome-typescript-loader` was that, in our case,
-it was a lot slower than [ts-loader](https://github.com/TypeStrong/ts-loader) on an incremental build (~20s vs ~3s).
-Secondly, we use [tslint](https://palantir.github.io/tslint) and we wanted to run this, along with type checker, in a separate process.
-This is why we've created this plugin. To provide better performance, plugin reuses Abstract Syntax Trees between compilations and shares
-these trees with tslint. It can be scaled with a multi-process mode to utilize maximum CPU power.
-
-## Modules resolution
-It's very important to be aware that **this plugin uses [typescript](https://github.com/Microsoft/TypeScript)'s, not
-[webpack](https://github.com/webpack/webpack)'s modules resolution**. It means that you have to setup `tsconfig.json` correctly. For example
-if you set `files: ['./src/someFile.ts']` in `tsconfig.json`, this plugin will check only `someFile.ts` for semantic errors. It's because
-of performance. The goal of this plugin is to be *as fast as possible*. With typescript's module resolution we don't have to wait for webpack
-to compile files (which traverses dependency graph during compilation) - we have a full list of files from the begin.
-
-To debug typescript's modules resolution, you can use `tsc --traceResolution` command.
-
-## TSLint
-If you have installed [tslint](https://palantir.github.io/tslint), you can enable it by setting `tslint: true` or
-`tslint: './path/to/tslint.json'`. We recommend changing `defaultSeverity` to a `"warning"` in `tslint.json` file.
-It helps to distinguish lints from typescript's diagnostics.
-
-## Options
-* **tsconfig** `string`:
-Path to *tsconfig.json* file. Default: `path.resolve(compiler.options.context, './tsconfig.json')`.
-
-* **tslint** `string | true`:
-Path to *tslint.json* file or `true`. If `true`, uses `path.resolve(compiler.options.context, './tslint.json')`. Default: `undefined`.
-
-* **watch** `string | string[]`:
-Directories or files to watch by service. Not necessary but improves performance (reduces number of `fs.stat` calls).
-
-* **async** `boolean`:
-True by default - `async: false` can block webpack's emit to wait for type checker/linter and to add errors to the webpack's compilation.
-We recommend to set this to `false` in projects where type checking is faster than webpack's build - it's better for integration with other plugins. Another scenario where you might want to set this to `false` is if you use the `overlay` functionality of `webpack-dev-server`.
-
-* **ignoreDiagnostics** `number[]`:
-List of typescript diagnostic codes to ignore.
-
-* **ignoreLints** `string[]`:
-List of tslint rule names to ignore.
-
-* **colors** `boolean`:
-If `false`, disables built-in colors in logger messages. Default: `true`.
-
-* **logger** `object`:
-Logger instance. It should be object that implements method: `error`, `warn`, `info`. Default: `console`.
-
-* **formatter** `'default' | 'codeframe' | ((message: NormalizedMessage, useColors: boolean) => string)`:
-Formatter for diagnostics and lints. By default uses `default` formatter. You can also pass your own formatter as a function
-(see `src/NormalizedMessage.js` and `src/formatter/` for api reference).
-
-* **formatterOptions** `object`:
-Options passed to formatters (currently only `codeframe` - see [available options](https://www.npmjs.com/package/babel-code-frame#options))
-
-* **silent** `boolean`:
-If `true`, logger will not be used. Default: `false`.
-
-* **checkSyntacticErrors** `boolean`:
-This option is useful if you're using ts-loader in `happyPackMode` with [HappyPack](https://github.com/amireh/happypack) or [thread-loader](https://github.com/webpack-contrib/thread-loader) to parallelise your builds. It will ensure that the plugin checks for both syntactic errors (eg `const array = [{} {}];`) and semantic errors (eg `const x: number = '1';`). By default the plugin only checks for semantic errors. This is because when ts-loader is used in `transpileOnly` mode, ts-loader will still report syntactic errors. When used in `happyPackMode` it does not. Default: `false`.
-
-* **memoryLimit** `number`:
-Memory limit for service process in MB. If service exits with allocation failed error, increase this number. Default: `2048`.
-
-* **workers** `number`:
-You can split type checking to a few workers to speed-up increment build. **Be careful** - if you don't want to increase build time, you
-should keep free 1 core for *build* and 1 core for a *system* *(for example system with 4 CPUs should use max 2 workers)*. Second thing -
-node doesn't share memory between workers - keep in mind that memory usage will increase. Be aware that in some scenarios increasing workers
-number **can increase checking time**. Default: `ForkTsCheckerWebpackPlugin.ONE_CPU`.
-
-* **vue** `boolean`:
-If `true`, the linter and compiler will process VueJs single-file-component (.vue) files. See the
-[Vue section](https://github.com/Realytics/fork-ts-checker-webpack-plugin#vue) further down for information on how to correctly setup your project.
-
-### Pre-computed consts:
- * `ForkTsCheckerWebpackPlugin.ONE_CPU` - always use one CPU
- * `ForkTsCheckerWebpackPlugin.ALL_CPUS` - always use all CPUs (will increase build time)
- * `ForkTsCheckerWebpackPlugin.ONE_CPU_FREE` - leave only one CPU for build (probably will increase build time)
- * `ForkTsCheckerWebpackPlugin.TWO_CPUS_FREE` - **recommended** - leave two CPUs free (one for build, one for system)
-
-## Different behaviour in watch mode
-
-If you turn on [webpacks watch mode](https://webpack.js.org/configuration/watch/#watch) the `fork-ts-checker-notifier-webpack-plugin` will take care of logging type errors, _not_ webpack itself. That means if you set `silent: true` you won't see type errors in your console in watch mode.
-
-You can either set `silent: false` to show the logging from `fork-ts-checker-notifier-webpack-plugin` _or_ set `async: false`. Now webpack itself will log type errors again, but note that this can slow down your builds depending on the size of your project.
-
-## Notifier
-
-You may already be using the excellent [webpack-notifier](https://github.com/Turbo87/webpack-notifier) plugin to make build failures more obvious in the form of system notifications. There's an equivalent notifier plugin designed to work with the `fork-ts-checker-webpack-plugin`. It is the `fork-ts-checker-notifier-webpack-plugin` and can be found [here](https://github.com/johnnyreilly/fork-ts-checker-notifier-webpack-plugin). This notifier deliberately has a similar API as the `webpack-notifier` plugin to make migration easier.
-
-## Known Issue Watching Non-Emitting Files
-
-At present there is an issue with the plugin regarding the triggering of type-checking when a change is made in a source file that will not emit js. If you have a file which contains only `interface`s and / or `type`s then changes to it will **not** trigger the type checker whilst in watch mode. Sorry about that.
-
-We hope this will be resolved in future; the issue can be tracked [here](https://github.com/Realytics/fork-ts-checker-webpack-plugin/issues/36).
-
-## Plugin Hooks
-This plugin provides some custom webpack hooks (all are sync):
-
-| Event name | Description | Params |
-|------------|-------------|--------|
-|`fork-ts-checker-cancel`| Cancellation has been requested | `cancellationToken` |
-|`fork-ts-checker-waiting`| Waiting for results | `hasTsLint` |
-|`fork-ts-checker-service-before-start`| Async plugin that can be used for delaying `fork-ts-checker-service-start` | - |
-|`fork-ts-checker-service-start`| Service will be started | `tsconfigPath`, `tslintPath`, `watchPaths`, `workersNumber`, `memoryLimit` |
-|`fork-ts-checker-service-start-error` | Cannot start service | `error` |
-|`fork-ts-checker-service-out-of-memory`| Service is out of memory | - |
-|`fork-ts-checker-receive`| Plugin receives diagnostics and lints from service | `diagnostics`, `lints` |
-|`fork-ts-checker-emit`| Service will add errors and warnings to webpack compilation ('build' mode) | `diagnostics`, `lints`, `elapsed` |
-|`fork-ts-checker-done`| Service finished type checking and webpack finished compilation ('watch' mode) | `diagnostics`, `lints`, `elapsed` |
-
-## Vue
-1. Turn on the vue option in the plugin in your webpack config:
-
-```
- new ForkTsCheckerWebpackPlugin({
- tslint: true,
- vue: true
- })
-```
-
-2. To activate TypeScript in your `.vue` files, you need to ensure your script tag's language attribute is set
-to `ts` or `tsx` (also make sure you include the `.vue` extension in all your import statements as shown below):
-
-```html
-
-```
-
-3. Ideally you are also using `ts-loader` (in transpileOnly mode). Your Webpack config rules may look something like this:
-
-```
-{
- test: /\.ts$/,
- loader: 'ts-loader',
- include: [resolve('src'), resolve('test')],
- options: {
- appendTsSuffixTo: [/\.vue$/],
- transpileOnly: true
- }
-},
-{
- test: /\.vue$/,
- loader: 'vue-loader',
- options: vueLoaderConfig
-},
-```
-4. Add rules to your `tslint.json` and they will be applied to Vue files. For example, you could apply the Standard JS rules [tslint-config-standard](https://github.com/blakeembrey/tslint-config-standard) like this:
-
-```json
-{
- "defaultSeverity": "error",
- "extends": [
- "tslint-config-standard"
- ]
-}
-```
-5. Ensure your `tsconfig.json` includes .vue files:
-
-```
-// tsconfig.json
-{
- "include": [
- "src/**/*.ts",
- "src/**/*.vue"
- ],
- "exclude": [
- "node_modules"
- ]
-}
-```
-
-6. It accepts any wildcard in your TypeScript configuration:
-```
-// tsconfig.json
-{
- "compilerOptions": {
-
- // ...
-
- "baseUrl": ".",
- "paths": {
- "@/*": [
- "src/*"
- ],
- "~/*": [
- "src/*"
- ]
- }
- }
-}
-
-// In a .ts or .vue file...
-import Hello from '@/components/hello.vue'
-```
-
-7. If you are working in **VSCode**, you can get extensions [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) and [TSLint Vue](https://marketplace.visualstudio.com/items?itemName=prograhammer.tslint-vue) to complete the developer workflow.
-
-## License
-MIT
+This is a fork of [`fork-ts-checker-webpack-plugin`](https://github.com/Realytics/fork-ts-checker-webpack-plugin). You probably want to use that package instead.
diff --git a/package.json b/package.json
index 0de7a273..4393052d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
- "name": "fork-ts-checker-webpack-plugin",
- "version": "0.4.10",
+ "name": "fork-ts-checker-webpack-plugin-alt",
+ "version": "0.4.14",
"description": "Runs typescript type checker and linter on separate process.",
"main": "lib/index.js",
"types": "lib/types/index.d.ts",
@@ -9,8 +9,8 @@
],
"scripts": {
"build": "tsc --version && tsc --project \"./src\"",
- "test:unit": "mocha -R spec ./test/unit",
- "test:integration": "mocha -R spec ./test/integration && rimraf tmp",
+ "test:unit": "mocha -R spec ./test/unit --exit",
+ "test:integration": "mocha -R spec ./test/integration --exit && rimraf tmp",
"test": "npm run build && npm run test:unit && npm run test:integration",
"test:watch": "mocha -R spec --watch ./test/unit",
"test:coverage": "rimraf coverage && istanbul cover -root lib --include-all-sources mocha -- -R spec ./test/unit ./test/integration",
@@ -18,7 +18,7 @@
"lint:fix": "tslint --project src/tsconfig.json --fix && eslint ./test --fix"
},
"repository": {
- "url": "https://github.com/Realytics/fork-ts-checker-webpack-plugin.git",
+ "url": "https://github.com/Timer/fork-ts-checker-webpack-plugin.git",
"type": "git"
},
"keywords": [
@@ -51,10 +51,8 @@
"devDependencies": {
"@types/babel-code-frame": "^6.20.1",
"@types/chokidar": "^1.7.5",
- "@types/lodash.endswith": "^4.2.3",
- "@types/lodash.isfunction": "^3.0.3",
- "@types/lodash.isstring": "^4.0.3",
- "@types/lodash.startswith": "^4.2.3",
+ "@types/lodash": "^4.14.117",
+ "@types/micromatch": "^3.1.0",
"@types/minimatch": "^3.0.1",
"@types/node": "^8.0.26",
"@types/resolve": "0.0.4",
@@ -65,7 +63,7 @@
"husky": "^1.1.2",
"istanbul": "^0.4.5",
"lint-staged": "^7.3.0",
- "mocha": "^3.4.1",
+ "mocha": "^5.2.0",
"mock-fs": "^4.3.0",
"mock-require": "^2.0.2",
"prettier": "^1.14.3",
@@ -82,18 +80,14 @@
"webpack": "^4.16.5"
},
"peerDependencies": {
- "tslint": "^4.0.0 || ^5.0.0",
- "typescript": "^2.1.0 || ^3.0.0",
"webpack": "^2.3.0 || ^3.0.0 || ^4.0.0"
},
"dependencies": {
"babel-code-frame": "^6.22.0",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
- "lodash.endswith": "^4.2.1",
- "lodash.isfunction": "^3.0.8",
- "lodash.isstring": "^4.0.1",
- "lodash.startswith": "^4.2.1",
+ "lodash": "^4.17.11",
+ "micromatch": "^3.1.10",
"minimatch": "^3.0.4",
"resolve": "^1.5.0",
"tapable": "^1.0.0"
diff --git a/src/CancellationToken.ts b/src/CancellationToken.ts
index 4f7d20ff..89a09a64 100644
--- a/src/CancellationToken.ts
+++ b/src/CancellationToken.ts
@@ -2,7 +2,7 @@ import * as crypto from 'crypto';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
-import * as ts from 'typescript';
+import { OperationCanceledException } from './OperationCanceledException';
interface CancellationTokenData {
isCancelled: boolean;
@@ -54,7 +54,7 @@ export class CancellationToken {
throwIfCancellationRequested() {
if (this.isCancellationRequested()) {
- throw new ts.OperationCanceledException();
+ throw new OperationCanceledException();
}
}
diff --git a/src/FilesRegister.ts b/src/FilesRegister.ts
index fc133000..ee4f95d0 100644
--- a/src/FilesRegister.ts
+++ b/src/FilesRegister.ts
@@ -1,3 +1,4 @@
+// tslint:disable-next-line:no-implicit-dependencies
import * as ts from 'typescript';
interface DataShape {
diff --git a/src/FilesWatcher.ts b/src/FilesWatcher.ts
index 54a1e279..67032ade 100644
--- a/src/FilesWatcher.ts
+++ b/src/FilesWatcher.ts
@@ -1,6 +1,6 @@
import * as chokidar from 'chokidar';
import * as path from 'path';
-import startsWith = require('lodash.startswith');
+import startsWith = require('lodash/startsWith');
export class FilesWatcher {
watchPaths: string[];
diff --git a/src/IncrementalChecker.ts b/src/IncrementalChecker.ts
index f6b8d9e6..ea99461d 100644
--- a/src/IncrementalChecker.ts
+++ b/src/IncrementalChecker.ts
@@ -1,7 +1,9 @@
import * as fs from 'fs';
-import endsWith = require('lodash.endswith');
+import endsWith = require('lodash/endsWith');
import * as path from 'path';
+// tslint:disable-next-line:no-implicit-dependencies
import * as ts from 'typescript';
+// tslint:disable-next-line:no-implicit-dependencies
import { Configuration, Linter } from 'tslint'; // Imported for types alone; actual requires take place in methods below
import { FilesRegister } from './FilesRegister';
import { FilesWatcher } from './FilesWatcher';
@@ -10,6 +12,7 @@ import { NormalizedMessage } from './NormalizedMessage';
import { CancellationToken } from './CancellationToken';
import * as minimatch from 'minimatch';
import { VueProgram } from './VueProgram';
+import { TypeScriptInstance } from './TypeScriptInstance';
// Need some augmentation here - linterOptions.exclude is not (yet) part of the official
// types for tslint.
@@ -22,6 +25,7 @@ interface ConfigurationFile extends Configuration.IConfigurationFile {
export class IncrementalChecker {
programConfigFile: string;
+ compilerOptions: object;
linterConfigFile: string | false;
watchPaths: string[];
workNumber: number;
@@ -33,6 +37,7 @@ export class IncrementalChecker {
linterConfig: ConfigurationFile;
linterExclusions: minimatch.IMinimatch[];
+ typescript: TypeScriptInstance;
program: ts.Program;
programConfig: ts.ParsedCommandLine;
watcher: FilesWatcher;
@@ -40,7 +45,9 @@ export class IncrementalChecker {
vue: boolean;
constructor(
+ typescriptPath: string,
programConfigFile: string,
+ compilerOptions: object,
linterConfigFile: string | false,
watchPaths: string[],
workNumber: number,
@@ -48,7 +55,9 @@ export class IncrementalChecker {
checkSyntacticErrors: boolean,
vue: boolean
) {
+ this.typescript = require(typescriptPath);
this.programConfigFile = programConfigFile;
+ this.compilerOptions = compilerOptions;
this.linterConfigFile = linterConfigFile;
this.watchPaths = watchPaths;
this.workNumber = workNumber || 0;
@@ -68,18 +77,33 @@ export class IncrementalChecker {
}));
}
- static loadProgramConfig(configFile: string) {
- return ts.parseJsonConfigFileContent(
- // Regardless of the setting in the tsconfig.json we want isolatedModules to be false
- Object.assign(ts.readConfigFile(configFile, ts.sys.readFile).config, {
- isolatedModules: false
- }),
- ts.sys,
+ static loadProgramConfig(
+ typescript: TypeScriptInstance,
+ configFile: string,
+ compilerOptions: object
+ ) {
+ const tsconfig = typescript.readConfigFile(
+ configFile,
+ typescript.sys.readFile
+ ).config;
+
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
+ tsconfig.compilerOptions = {
+ ...tsconfig.compilerOptions,
+ ...compilerOptions
+ };
+
+ const parsed = typescript.parseJsonConfigFileContent(
+ tsconfig,
+ typescript.sys,
path.dirname(configFile)
);
+
+ return parsed;
}
static loadLinterConfig(configFile: string): ConfigurationFile {
+ // tslint:disable-next-line:no-implicit-dependencies
const tslint = require('tslint');
return tslint.Configuration.loadConfigurationFromPath(
@@ -88,12 +112,13 @@ export class IncrementalChecker {
}
static createProgram(
+ typescript: TypeScriptInstance,
programConfig: ts.ParsedCommandLine,
files: FilesRegister,
watcher: FilesWatcher,
oldProgram: ts.Program
) {
- const host = ts.createCompilerHost(programConfig.options);
+ const host = typescript.createCompilerHost(programConfig.options);
const realGetSourceFile = host.getSourceFile;
host.getSourceFile = (filePath, languageVersion, onError) => {
@@ -119,7 +144,7 @@ export class IncrementalChecker {
return files.getData(filePath).source;
};
- return ts.createProgram(
+ return typescript.createProgram(
programConfig.fileNames,
programConfig.options,
host,
@@ -128,6 +153,7 @@ export class IncrementalChecker {
}
static createLinter(program: ts.Program) {
+ // tslint:disable-next-line:no-implicit-dependencies
const tslint = require('tslint');
return new tslint.Linter({ fix: false }, program);
@@ -189,9 +215,14 @@ export class IncrementalChecker {
loadVueProgram() {
this.programConfig =
this.programConfig ||
- VueProgram.loadProgramConfig(this.programConfigFile);
+ VueProgram.loadProgramConfig(
+ this.typescript,
+ this.programConfigFile,
+ this.compilerOptions
+ );
return VueProgram.createProgram(
+ this.typescript,
this.programConfig,
path.dirname(this.programConfigFile),
this.files,
@@ -203,9 +234,14 @@ export class IncrementalChecker {
loadDefaultProgram() {
this.programConfig =
this.programConfig ||
- IncrementalChecker.loadProgramConfig(this.programConfigFile);
+ IncrementalChecker.loadProgramConfig(
+ this.typescript,
+ this.programConfigFile,
+ this.compilerOptions
+ );
return IncrementalChecker.createProgram(
+ this.typescript,
this.programConfig,
this.files,
this.watcher,
@@ -254,7 +290,12 @@ export class IncrementalChecker {
// normalize and deduplicate diagnostics
return NormalizedMessage.deduplicate(
- diagnostics.map(NormalizedMessage.createFromDiagnostic)
+ diagnostics.map(d =>
+ NormalizedMessage.createFromDiagnostic(
+ this.typescript.flattenDiagnosticMessageText,
+ d
+ )
+ )
);
}
diff --git a/src/NormalizedMessage.ts b/src/NormalizedMessage.ts
index 2256a1e1..161f9c71 100644
--- a/src/NormalizedMessage.ts
+++ b/src/NormalizedMessage.ts
@@ -1,8 +1,6 @@
-import {
- Diagnostic,
- DiagnosticCategory,
- flattenDiagnosticMessageText
-} from 'typescript';
+// tslint:disable-next-line:no-implicit-dependencies
+import { Diagnostic, DiagnosticMessageChain } from 'typescript';
+// tslint:disable-next-line:no-implicit-dependencies
import { RuleFailure } from 'tslint';
type ErrorType = 'diagnostic' | 'lint';
@@ -45,7 +43,13 @@ export class NormalizedMessage {
}
// message types
- static createFromDiagnostic(diagnostic: Diagnostic) {
+ static createFromDiagnostic(
+ flattenDiagnosticMessageText: (
+ messageText: string | DiagnosticMessageChain | undefined,
+ newLine: string
+ ) => string,
+ diagnostic: Diagnostic
+ ) {
let file: string;
let line: number;
let character: number;
@@ -61,9 +65,10 @@ export class NormalizedMessage {
return new NormalizedMessage({
type: NormalizedMessage.TYPE_DIAGNOSTIC,
code: diagnostic.code,
- severity: DiagnosticCategory[
- diagnostic.category
- ].toLowerCase() as Severity,
+ // TODO: Keep in sync with TypeScript's DiagnosticCategory.Error or pass in
+ severity: (diagnostic.category.toString() === '1'
+ ? NormalizedMessage.SEVERITY_ERROR
+ : NormalizedMessage.SEVERITY_WARNING) as Severity,
content: flattenDiagnosticMessageText(diagnostic.messageText, '\n'),
file,
line,
diff --git a/src/OperationCanceledException.ts b/src/OperationCanceledException.ts
new file mode 100644
index 00000000..51440b7e
--- /dev/null
+++ b/src/OperationCanceledException.ts
@@ -0,0 +1 @@
+export class OperationCanceledException {}
diff --git a/src/TypeScriptInstance.ts b/src/TypeScriptInstance.ts
new file mode 100644
index 00000000..8c9c815a
--- /dev/null
+++ b/src/TypeScriptInstance.ts
@@ -0,0 +1,30 @@
+// tslint:disable-next-line:no-implicit-dependencies
+import * as ts from 'typescript';
+
+// TODO: keep in sync with TypeScript
+export enum ScriptKind {
+ Unknown = 0,
+ JS = 1,
+ JSX = 2,
+ TS = 3,
+ TSX = 4,
+ External = 5,
+ JSON = 6,
+ /**
+ * Used on extensions that doesn't define the ScriptKind but the content defines it.
+ * Deferred extensions are going to be included in all project contexts.
+ */
+ Deferred = 7
+}
+
+export interface TypeScriptInstance {
+ parseJsonConfigFileContent: typeof ts.parseJsonConfigFileContent;
+ readConfigFile: typeof ts.readConfigFile;
+ createCompilerHost: typeof ts.createCompilerHost;
+ createProgram: typeof ts.createProgram;
+ flattenDiagnosticMessageText: typeof ts.flattenDiagnosticMessageText;
+ resolveModuleName: typeof ts.resolveModuleName;
+ createSourceFile: typeof ts.createSourceFile;
+ version: typeof ts.version;
+ sys: typeof ts.sys;
+}
diff --git a/src/VueProgram.ts b/src/VueProgram.ts
index 5dc42e43..5b668dff 100644
--- a/src/VueProgram.ts
+++ b/src/VueProgram.ts
@@ -1,8 +1,10 @@
import * as fs from 'fs';
import * as path from 'path';
+// tslint:disable-next-line:no-implicit-dependencies
import * as ts from 'typescript';
import { FilesRegister } from './FilesRegister';
import { FilesWatcher } from './FilesWatcher';
+import { ScriptKind, TypeScriptInstance } from './TypeScriptInstance';
// tslint:disable-next-line
import * as vueCompiler from 'vue-template-compiler';
@@ -12,15 +14,15 @@ interface ResolvedScript {
}
export class VueProgram {
- static loadProgramConfig(configFile: string) {
+ static loadProgramConfig(typescript: TypeScriptInstance, configFile: string, compilerOptions: object) {
const extraExtensions = ['vue'];
const parseConfigHost: ts.ParseConfigHost = {
- fileExists: ts.sys.fileExists,
- readFile: ts.sys.readFile,
- useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
+ fileExists: typescript.sys.fileExists,
+ readFile: typescript.sys.readFile,
+ useCaseSensitiveFileNames: typescript.sys.useCaseSensitiveFileNames,
readDirectory: (rootDir, extensions, excludes, includes, depth) => {
- return ts.sys.readDirectory(
+ return typescript.sys.readDirectory(
rootDir,
extensions.concat(extraExtensions),
excludes,
@@ -30,11 +32,16 @@ export class VueProgram {
}
};
- const parsed = ts.parseJsonConfigFileContent(
- // Regardless of the setting in the tsconfig.json we want isolatedModules to be false
- Object.assign(ts.readConfigFile(configFile, ts.sys.readFile).config, {
- isolatedModules: false
- }),
+ const tsconfig = typescript.readConfigFile(configFile, typescript.sys.readFile).config;
+
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
+ tsconfig.compilerOptions = {
+ ...tsconfig.compilerOptions,
+ ...compilerOptions
+ };
+
+ const parsed = typescript.parseJsonConfigFileContent(
+ tsconfig,
parseConfigHost,
path.dirname(configFile)
);
@@ -102,13 +109,14 @@ export class VueProgram {
}
static createProgram(
+ typescript: TypeScriptInstance,
programConfig: ts.ParsedCommandLine,
basedir: string,
files: FilesRegister,
watcher: FilesWatcher,
oldProgram: ts.Program
) {
- const host = ts.createCompilerHost(programConfig.options);
+ const host = typescript.createCompilerHost(programConfig.options);
const realGetSourceFile = host.getSourceFile;
// We need a host that can parse Vue SFCs (single file components).
@@ -137,7 +145,7 @@ export class VueProgram {
// get typescript contents from Vue file
if (source && VueProgram.isVue(filePath)) {
const resolved = VueProgram.resolveScriptBlock(source.text);
- source = ts.createSourceFile(
+ source = typescript.createSourceFile(
filePath,
resolved.content,
languageVersion,
@@ -155,7 +163,7 @@ export class VueProgram {
for (const moduleName of moduleNames) {
// Try to use standard resolution.
- const { resolvedModule } = ts.resolveModuleName(
+ const { resolvedModule } = typescript.resolveModuleName(
moduleName,
containingFile,
programConfig.options,
@@ -221,7 +229,7 @@ export class VueProgram {
return resolvedModules;
};
- return ts.createProgram(
+ return typescript.createProgram(
programConfig.fileNames,
programConfig.options,
host,
@@ -231,14 +239,14 @@ export class VueProgram {
private static getScriptKindByLang(lang: string) {
if (lang === 'ts') {
- return ts.ScriptKind.TS;
+ return ScriptKind.TS;
} else if (lang === 'tsx') {
- return ts.ScriptKind.TSX;
+ return ScriptKind.TSX;
} else if (lang === 'jsx') {
- return ts.ScriptKind.JSX;
+ return ScriptKind.JSX;
} else {
// when lang is "js" or no lang specified
- return ts.ScriptKind.JS;
+ return ScriptKind.JS;
}
}
@@ -264,7 +272,7 @@ export class VueProgram {
// No