diff --git a/README.md b/README.md index a471cfe4..defb3ca0 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ * Speeds up [TypeScript](https://github.com/Microsoft/TypeScript) type checking (by moving it to a separate process) 🏎 * Supports modern TypeScript features like [project references](https://www.typescriptlang.org/docs/handbook/project-references.html) and [incremental mode](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental-flag) ✨ - * Supports [Vue Single File Component](https://vuejs.org/v2/guide/single-file-components.html) ✅  * Displays nice error messages with the [code frame](https://babeljs.io/docs/en/next/babel-code-frame.html) formatter 🌈 ## Installation @@ -28,6 +27,7 @@ This plugin requires **Node.js >=12.13.0+**, **Webpack ^5.11.0**, **TypeScript ^ * If you depend on **TypeScript 2.1 - 2.6.2**, please use [version 4](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/tree/v4.1.4) of the plugin. * If you depend on **Webpack 4**, **TypeScript 2.7 - 3.5.3** or **ESLint** feature, please use [version 6](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/tree/v6.2.6) of the plugin. +* If you need Vue.js support, please use [version 6](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/tree/v6.5.2) of ths plugin ```sh # with npm @@ -115,20 +115,9 @@ Options for the TypeScript checker (`typescript` option object). | `build` | `boolean` | `false` | The equivalent of the `--build` flag for the `tsc` command. | | `mode` | `'readonly'` or `'write-dts'` or `'write-tsbuildinfo'` or `'write-references'` | `build === true ? 'write-tsbuildinfo' ? 'readonly'` | Use `readonly` if you don't want to write anything on the disk, `write-dts` to write only `.d.ts` files, `write-tsbuildinfo` to write only `.tsbuildinfo` files, `write-references` to write both `.js` and `.d.ts` files of project references (last 2 modes requires `build: true`). | | `diagnosticOptions` | `object` | `{ syntactic: false, semantic: true, declaration: false, global: false }` | Settings to select which diagnostics do we want to perform. | -| `extensions` | `object` | `{}` | See [TypeScript extensions options](#typescript-extensions-options). | | `profile` | `boolean` | `false` | Measures and prints timings related to the TypeScript performance. | | `typescriptPath` | `string` | `require.resolve('typescript')` | If supplied this is a custom path where TypeScript can be found. | -#### TypeScript extensions options - -Options for the TypeScript checker extensions (`typescript.extensions` option object). - -| Name | Type | Default value | Description | -|----------------|-----------------------|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `vue` | `object` or `boolean` | `false` | If `true`, it enables Vue [Single File Component](https://vuejs.org/v2/guide/single-file-components.html) support. | -| `vue.enabled` | `boolean` | `false` | Same as the `vue` option | -| `vue.compiler` | `string` | `'vue-template-compiler'` | The package name of the compiler that will be used to parse `.vue` files. You can use `'nativescript-vue-template-compiler'` if you use [nativescript-vue](https://github.com/nativescript-vue/nativescript-vue) | - ### Issues options Options for the issues filtering (`issue` option object). @@ -176,120 +165,6 @@ module.exports = { -## Vue.js - -⚠️ There are additional **constraints** regarding Vue.js Single File Component support: ⚠️ - * It requires **TypeScript >= 3.8.0** (it's a limitation of the `transpileOnly` mode from `ts-loader`) - * It doesn't work with the `build` mode (project references) - -To enable Vue.js support, follow these steps: - -
-Expand Vue.js set up instruction - -1. Ensure you have all required packages installed: -```sh -# with npm -npm install --save vue vue-class-component -npm install --save-dev vue-loader ts-loader css-loader vue-template-compiler - -# with yarn -yarn add vue vue-class-component -yarn add --dev vue-loader ts-loader css-loader vue-template-compiler -``` - -2. Add `tsconfig.json` configuration: -```json -{ - "compilerOptions": { - "experimentalDecorators": true, - "jsx": "preserve", - "target": "ES5", - "lib": ["ES6", "DOM"], - "baseUrl": ".", - "paths": { - "@/*": ["src/*"], - "~/*": ["src/*"] - }, - "sourceMap": true, - "importsNotUsedAsValues": "preserve" - }, - "include": [ - "src/**/*.ts", - "src/**/*.vue" - ], - "exclude": [ - "node_modules" - ] -} -``` - -3. Add `webpack.config.js` configuration: -```js -const path = require('path'); -const VueLoaderPlugin = require('vue-loader/lib/plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); - -module.exports = { - entry: './src/index.ts', - output: { - filename: 'index.js', - path: path.resolve(__dirname, 'dist'), - }, - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader' - }, - { - test: /\.ts$/, - loader: 'ts-loader', - exclude: /node_modules/, - options: { - appendTsSuffixTo: [/\.vue$/], - // add transpileOnly option if you use ts-loader < 9.3.0 - // transpileOnly: true - } - }, - { - test: /\.css$/, - loader: 'css-loader' - }, - ], - }, - resolve: { - extensions: ['.ts', '.js', '.vue', '.json'], - alias: { - '@': path.resolve(__dirname, './src'), - '~': path.resolve(__dirname, './src'), - } - }, - plugins: [ - new VueLoaderPlugin(), - new ForkTsCheckerWebpackPlugin({ - typescript: { - extensions: { - vue: true - } - } - }) - ] -}; -``` - -4. Add `src/types/vue.d.ts` file to shim `.vue` modules: -```typescript -declare module "*.vue" { - import Vue from "vue"; - export default Vue; -} -``` - -5. If you are working in VSCode, you can get the [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) extension to complete the developer workflow. - -
- ## Plugin hooks This plugin provides some custom webpack hooks: diff --git a/package.json b/package.json index 2e3c6b36..cb0a5c97 100644 --- a/package.json +++ b/package.json @@ -70,14 +70,8 @@ }, "peerDependencies": { "typescript": ">3.6.0", - "vue-template-compiler": "*", "webpack": "^5.11.0" }, - "peerDependenciesMeta": { - "vue-template-compiler": { - "optional": true - } - }, "devDependencies": { "@commitlint/config-conventional": "^16.0.0", "@semantic-release/commit-analyzer": "^8.0.1", diff --git a/src/plugin-options.json b/src/plugin-options.json index 9132ebfe..f30663d7 100644 --- a/src/plugin-options.json +++ b/src/plugin-options.json @@ -159,14 +159,6 @@ } } }, - "extensions": { - "type": "object", - "properties": { - "vue": { - "$ref": "#/definitions/TypeScriptVueExtensionOptions" - } - } - }, "profile": { "type": "boolean", "description": "Measures and prints timings related to the TypeScript performance." @@ -177,27 +169,6 @@ } } }, - "TypeScriptVueExtensionOptions": { - "oneOf": [ - { - "type": "boolean", - "description": "Enable TypeScript Vue extension." - }, - { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Enable TypeScript Vue extension." - }, - "compiler": { - "type": "string", - "description": "Custom vue-template-compiler package" - } - } - } - ] - }, "FormatterOptions": { "oneOf": [ { diff --git a/src/typescript/extension/type-script-embedded-extension.ts b/src/typescript/extension/type-script-embedded-extension.ts deleted file mode 100644 index 02f6d454..00000000 --- a/src/typescript/extension/type-script-embedded-extension.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { extname } from 'path'; - -import type * as ts from 'typescript'; - -import type { FilesMatch } from '../../files-match'; -import type { Issue } from '../../issue'; - -import type { TypeScriptExtension } from './type-script-extension'; - -interface TypeScriptEmbeddedSource { - sourceText: string; - extension: '.ts' | '.tsx' | '.js'; -} - -interface TypeScriptEmbeddedExtensionHost { - embeddedExtensions: string[]; - getEmbeddedSource(fileName: string): TypeScriptEmbeddedSource | undefined; -} - -/** - * It handles most of the logic required to process embedded TypeScript code (like in Vue components or MDX) - * - * @param embeddedExtensions List of file extensions that should be treated as an embedded TypeScript source - * (for example ['.vue']) - * @param getEmbeddedSource Function that returns embedded TypeScript source text and extension that this file - * would have if it would be a regular TypeScript file - */ -function createTypeScriptEmbeddedExtension({ - embeddedExtensions, - getEmbeddedSource, -}: TypeScriptEmbeddedExtensionHost): TypeScriptExtension { - const embeddedSourceCache = new Map(); - - function getCachedEmbeddedSource(fileName: string) { - if (!embeddedSourceCache.has(fileName)) { - embeddedSourceCache.set(fileName, getEmbeddedSource(fileName)); - } - - return embeddedSourceCache.get(fileName); - } - - function parsePotentiallyEmbeddedFileName(fileName: string) { - const extension = extname(fileName); - const embeddedFileName = fileName.slice(0, fileName.length - extension.length); - const embeddedExtension = extname(embeddedFileName); - - return { - extension, - embeddedFileName, - embeddedExtension, - }; - } - - type FileExists = (fileName: string) => boolean; - function createEmbeddedFileExists(fileExists: FileExists): FileExists { - return function embeddedFileExists(fileName) { - const { embeddedExtension, embeddedFileName, extension } = - parsePotentiallyEmbeddedFileName(fileName); - - if (embeddedExtensions.includes(embeddedExtension) && fileExists(embeddedFileName)) { - const embeddedSource = getCachedEmbeddedSource(embeddedFileName); - return !!(embeddedSource && embeddedSource.extension === extension); - } - - return fileExists(fileName); - }; - } - - type ReadFile = (fileName: string, encoding?: string) => string | undefined; - function createEmbeddedReadFile(readFile: ReadFile): ReadFile { - return function embeddedReadFile(fileName, encoding) { - const { embeddedExtension, embeddedFileName, extension } = - parsePotentiallyEmbeddedFileName(fileName); - - if (embeddedExtensions.includes(embeddedExtension)) { - const embeddedSource = getCachedEmbeddedSource(embeddedFileName); - - if (embeddedSource && embeddedSource.extension === extension) { - return embeddedSource.sourceText; - } - } - - return readFile(fileName, encoding); - }; - } - - return { - extendIssues(issues: Issue[]): Issue[] { - return issues.map((issue) => { - if (issue.file) { - const { embeddedExtension, embeddedFileName } = parsePotentiallyEmbeddedFileName( - issue.file - ); - - if (embeddedExtensions.includes(embeddedExtension)) { - return { - ...issue, - file: embeddedFileName, - }; - } - } - - return issue; - }); - }, - extendWatchCompilerHost(host) { - return { - ...host, - watchFile(fileName, callback, poolingInterval) { - const { embeddedExtension, embeddedFileName } = - parsePotentiallyEmbeddedFileName(fileName); - - if (embeddedExtensions.includes(embeddedExtension)) { - return host.watchFile( - embeddedFileName, - (innerFileName: string, eventKind: ts.FileWatcherEventKind) => { - embeddedSourceCache.delete(embeddedFileName); - return callback(fileName, eventKind); - }, - poolingInterval - ); - } else { - return host.watchFile(fileName, callback, poolingInterval); - } - }, - readFile: createEmbeddedReadFile(host.readFile), - fileExists: createEmbeddedFileExists(host.fileExists), - }; - }, - extendCompilerHost(host) { - return { - ...host, - readFile: createEmbeddedReadFile(host.readFile), - fileExists: createEmbeddedFileExists(host.fileExists), - }; - }, - extendParseConfigFileHost(host: THost): THost { - return { - ...host, - readDirectory( - rootDir: string, - extensions: readonly string[], - excludes: readonly string[] | undefined, - includes: readonly string[], - depth?: number - ): readonly string[] { - return host - .readDirectory( - rootDir, - [...extensions, ...embeddedExtensions], - excludes, - includes, - depth - ) - .map((fileName) => { - const isEmbeddedFile = embeddedExtensions.some((embeddedExtension) => - fileName.endsWith(embeddedExtension) - ); - - if (isEmbeddedFile) { - const embeddedSource = getCachedEmbeddedSource(fileName); - - return embeddedSource ? `${fileName}${embeddedSource.extension}` : fileName; - } else { - return fileName; - } - }); - }, - }; - }, - extendDependencies(dependencies: FilesMatch) { - return { - ...dependencies, - files: dependencies.files.map((fileName) => { - const { embeddedExtension, embeddedFileName, extension } = - parsePotentiallyEmbeddedFileName(fileName); - - if (embeddedExtensions.includes(embeddedExtension)) { - const embeddedSource = getCachedEmbeddedSource(embeddedFileName); - if (embeddedSource && embeddedSource.extension === extension) { - return embeddedFileName; - } - } - - return fileName; - }), - extensions: [...dependencies.extensions, ...embeddedExtensions], - }; - }, - }; -} - -export { - TypeScriptEmbeddedExtensionHost, - TypeScriptEmbeddedSource, - createTypeScriptEmbeddedExtension, -}; diff --git a/src/typescript/extension/type-script-extension.ts b/src/typescript/extension/type-script-extension.ts deleted file mode 100644 index 2f9466e6..00000000 --- a/src/typescript/extension/type-script-extension.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type * as ts from 'typescript'; - -import type { FilesMatch } from '../../files-match'; -import type { Issue } from '../../issue'; - -interface TypeScriptHostExtension { - extendWatchSolutionBuilderHost?< - TProgram extends ts.BuilderProgram, - THost extends ts.SolutionBuilderWithWatchHost - >( - host: THost, - parsedCommandLine?: ts.ParsedCommandLine - ): THost; - extendWatchCompilerHost?< - TProgram extends ts.BuilderProgram, - THost extends ts.WatchCompilerHost - >( - host: THost, - parsedCommandLine?: ts.ParsedCommandLine - ): THost; - extendCompilerHost?( - host: THost, - parsedCommandLine?: ts.ParsedCommandLine - ): THost; - extendParseConfigFileHost?(host: THost): THost; -} - -interface TypeScriptReporterExtension { - extendIssues?(issues: Issue[]): Issue[]; - extendDependencies?(dependencies: FilesMatch): FilesMatch; -} - -interface TypeScriptExtension extends TypeScriptHostExtension, TypeScriptReporterExtension {} - -export { TypeScriptExtension, TypeScriptReporterExtension, TypeScriptHostExtension }; diff --git a/src/typescript/extension/vue/type-script-vue-extension-config.ts b/src/typescript/extension/vue/type-script-vue-extension-config.ts deleted file mode 100644 index b0027f1e..00000000 --- a/src/typescript/extension/vue/type-script-vue-extension-config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { TypeScriptVueExtensionOptions } from './type-script-vue-extension-options'; - -interface TypeScriptVueExtensionConfig { - enabled: boolean; - compiler: string; -} - -function createTypeScriptVueExtensionConfig( - options: TypeScriptVueExtensionOptions | undefined -): TypeScriptVueExtensionConfig { - return { - enabled: options === true, - compiler: 'vue-template-compiler', - ...(typeof options === 'object' ? options : {}), - }; -} - -export { TypeScriptVueExtensionConfig, createTypeScriptVueExtensionConfig }; diff --git a/src/typescript/extension/vue/type-script-vue-extension-options.ts b/src/typescript/extension/vue/type-script-vue-extension-options.ts deleted file mode 100644 index d92beff4..00000000 --- a/src/typescript/extension/vue/type-script-vue-extension-options.ts +++ /dev/null @@ -1,8 +0,0 @@ -type TypeScriptVueExtensionOptions = - | boolean - | { - enabled?: boolean; - compiler?: string; - }; - -export { TypeScriptVueExtensionOptions }; diff --git a/src/typescript/extension/vue/type-script-vue-extension-support.ts b/src/typescript/extension/vue/type-script-vue-extension-support.ts deleted file mode 100644 index 713806a8..00000000 --- a/src/typescript/extension/vue/type-script-vue-extension-support.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { TypeScriptVueExtensionConfig } from './type-script-vue-extension-config'; - -function assertTypeScriptVueExtensionSupport(config: TypeScriptVueExtensionConfig) { - // We need to import template compiler for vue lazily because it cannot be included it - // as direct dependency because it is an optional dependency of fork-ts-checker-webpack-plugin. - // Since its version must not mismatch with user-installed Vue.js, - // we should let the users install template compiler for vue by themselves. - const compilerName = config.compiler; - - try { - require(compilerName); - } catch (error) { - throw new Error( - [ - `Could not initialize '${compilerName}'. When you use 'typescript.extensions.vue' option, make sure to install '${compilerName}' and that the version matches that of 'vue'.`, - `Error details: ${String(error)}`, - ].join('\n') - ); - } -} - -export { assertTypeScriptVueExtensionSupport }; diff --git a/src/typescript/extension/vue/type-script-vue-extension.ts b/src/typescript/extension/vue/type-script-vue-extension.ts deleted file mode 100644 index 3ef1353e..00000000 --- a/src/typescript/extension/vue/type-script-vue-extension.ts +++ /dev/null @@ -1,157 +0,0 @@ -import fs from 'fs-extra'; - -import type { TypeScriptEmbeddedSource } from '../type-script-embedded-extension'; -import { createTypeScriptEmbeddedExtension } from '../type-script-embedded-extension'; -import type { TypeScriptExtension } from '../type-script-extension'; - -import type { TypeScriptVueExtensionConfig } from './type-script-vue-extension-config'; -import type { VueTemplateCompilerV2 } from './types/vue-template-compiler'; -import type { VueTemplateCompilerV3 } from './types/vue__compiler-sfc'; - -interface GenericScriptSFCBlock { - content: string; - attrs: Record; - start?: number; - end?: number; - lang?: string; - src?: string; -} - -function createTypeScriptVueExtension(config: TypeScriptVueExtensionConfig): TypeScriptExtension { - function loadVueTemplateCompiler(): VueTemplateCompilerV2 | VueTemplateCompilerV3 { - return require(config.compiler); - } - - function isVueTemplateCompilerV2( - compiler: VueTemplateCompilerV2 | VueTemplateCompilerV3 - ): compiler is VueTemplateCompilerV2 { - return typeof (compiler as VueTemplateCompilerV2).parseComponent === 'function'; - } - - function isVueTemplateCompilerV3( - compiler: VueTemplateCompilerV2 | VueTemplateCompilerV3 - ): compiler is VueTemplateCompilerV3 { - return typeof (compiler as VueTemplateCompilerV3).parse === 'function'; - } - - function getExtensionByLang( - lang: string | true | undefined - ): TypeScriptEmbeddedSource['extension'] { - if (lang === true) { - return '.js'; - } - - switch (lang) { - case 'ts': - return '.ts'; - case 'tsx': - return '.tsx'; - case 'js': - case 'jsx': - default: - return '.js'; - } - } - - function createVueNoScriptEmbeddedSource(): TypeScriptEmbeddedSource { - return { - sourceText: 'export default {};\n', - extension: '.js', - }; - } - - function createVueSrcScriptEmbeddedSource( - src: string, - lang: string | true | undefined - ): TypeScriptEmbeddedSource { - // Import path cannot be end with '.ts[x]' - src = src.replace(/\.tsx?$/i, ''); - - // For now, ignore the error when the src file is not found since it will produce incorrect code location. - // It's not a large problem since it's handled on webpack side. - const text = [ - '// @ts-ignore', - `export { default } from '${src}';`, - '// @ts-ignore', - `export * from '${src}';`, - ].join('\n'); - - return { - sourceText: text, - extension: getExtensionByLang(lang), - }; - } - - function createVueInlineScriptEmbeddedSource( - text: string, - lang: string | true | undefined - ): TypeScriptEmbeddedSource { - return { - sourceText: text, - extension: getExtensionByLang(lang), - }; - } - - function getVueEmbeddedSource(fileName: string): TypeScriptEmbeddedSource | undefined { - if (!fs.existsSync(fileName)) { - return undefined; - } - - const compiler = loadVueTemplateCompiler(); - const vueSourceText = fs.readFileSync(fileName, { encoding: 'utf-8' }); - - let script: GenericScriptSFCBlock | undefined; - if (isVueTemplateCompilerV2(compiler)) { - const parsed = compiler.parseComponent(vueSourceText, { - pad: 'space', - }); - - script = parsed.script; - } else if (isVueTemplateCompilerV3(compiler)) { - const parsed = compiler.parse(vueSourceText); - - if (parsed.descriptor && parsed.descriptor.script) { - const scriptV3 = parsed.descriptor.script; - - // map newer version of SFCScriptBlock to the generic one - script = { - content: scriptV3.content, - attrs: scriptV3.attrs, - start: scriptV3.loc.start.offset, - end: scriptV3.loc.end.offset, - lang: scriptV3.lang, - src: scriptV3.src, - }; - } - } else { - throw new Error( - 'Unsupported vue template compiler. Compiler should provide `parse` or `parseComponent` function.' - ); - } - - if (!script) { - // No block - // pad blank lines to retain diagnostics location - const lineOffset = vueSourceText.slice(0, script.start).split(/\r?\n/g).length; - const paddedSourceText = - Array(lineOffset).join('\n') + vueSourceText.slice(script.start, script.end); - - return createVueInlineScriptEmbeddedSource(paddedSourceText, script.attrs.lang); - } - } - - return createTypeScriptEmbeddedExtension({ - embeddedExtensions: ['.vue'], - getEmbeddedSource: getVueEmbeddedSource, - }); -} - -export { createTypeScriptVueExtension }; diff --git a/src/typescript/extension/vue/types/vue-template-compiler.ts b/src/typescript/extension/vue/types/vue-template-compiler.ts deleted file mode 100644 index 8ce51b8a..00000000 --- a/src/typescript/extension/vue/types/vue-template-compiler.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * This declaration is copied from https://github.com/vuejs/vue/pull/7918 - * which may included vue-template-compiler v2.6.0. - */ -interface SFCParserOptionsV2 { - pad?: true | 'line' | 'space'; -} - -export interface SFCBlockV2 { - type: string; - content: string; - attrs: Record; - start?: number; - end?: number; - lang?: string; - src?: string; - scoped?: boolean; - module?: string | boolean; -} - -export interface SFCDescriptorV2 { - template: SFCBlockV2 | undefined; - script: SFCBlockV2 | undefined; - styles: SFCBlockV2[]; - customBlocks: SFCBlockV2[]; -} - -export interface VueTemplateCompilerV2 { - parseComponent(file: string, options?: SFCParserOptionsV2): SFCDescriptorV2; -} diff --git a/src/typescript/extension/vue/types/vue__compiler-sfc.ts b/src/typescript/extension/vue/types/vue__compiler-sfc.ts deleted file mode 100644 index eada888d..00000000 --- a/src/typescript/extension/vue/types/vue__compiler-sfc.ts +++ /dev/null @@ -1,43 +0,0 @@ -interface Position { - offset: number; - line: number; - column: number; -} - -interface SourceLocation { - start: Position; - end: Position; - source: string; -} - -export interface SFCBlock { - type: string; - content: string; - attrs: Record; - loc: SourceLocation; - lang?: string; - src?: string; -} - -interface SFCDescriptor { - filename: string; - template: SFCBlock | null; - script: SFCBlock | null; - styles: SFCBlock[]; - customBlocks: SFCBlock[]; -} - -interface CompilerError extends SyntaxError { - code: number; - loc?: SourceLocation; -} - -interface SFCParseResult { - descriptor: SFCDescriptor; - errors: CompilerError[]; -} - -export interface VueTemplateCompilerV3 { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - parse(template: string, options?: any): SFCParseResult; -} diff --git a/src/typescript/type-script-support.ts b/src/typescript/type-script-support.ts index 5d75bd89..00648ef3 100644 --- a/src/typescript/type-script-support.ts +++ b/src/typescript/type-script-support.ts @@ -3,7 +3,6 @@ import os from 'os'; import fs from 'fs-extra'; import * as semver from 'semver'; -import { assertTypeScriptVueExtensionSupport } from './extension/vue/type-script-vue-extension-support'; import type { TypeScriptWorkerConfig } from './type-script-worker-config'; function assertTypeScriptSupport(config: TypeScriptWorkerConfig) { @@ -50,10 +49,6 @@ function assertTypeScriptSupport(config: TypeScriptWorkerConfig) { ].join(os.EOL) ); } - - if (config.extensions.vue.enabled) { - assertTypeScriptVueExtensionSupport(config.extensions.vue); - } } export { assertTypeScriptSupport }; diff --git a/src/typescript/type-script-worker-config.ts b/src/typescript/type-script-worker-config.ts index dae89888..a92a4c8a 100644 --- a/src/typescript/type-script-worker-config.ts +++ b/src/typescript/type-script-worker-config.ts @@ -2,8 +2,6 @@ import path from 'path'; import type webpack from 'webpack'; -import type { TypeScriptVueExtensionConfig } from './extension/vue/type-script-vue-extension-config'; -import { createTypeScriptVueExtensionConfig } from './extension/vue/type-script-vue-extension-config'; import type { TypeScriptConfigOverwrite } from './type-script-config-overwrite'; import type { TypeScriptDiagnosticsOptions } from './type-script-diagnostics-options'; import type { TypeScriptWorkerOptions } from './type-script-worker-options'; @@ -17,9 +15,6 @@ interface TypeScriptWorkerConfig { context: string; mode: 'readonly' | 'write-dts' | 'write-tsbuildinfo' | 'write-references'; diagnosticOptions: TypeScriptDiagnosticsOptions; - extensions: { - vue: TypeScriptVueExtensionConfig; - }; profile: boolean; typescriptPath: string; } @@ -53,11 +48,6 @@ function createTypeScriptWorkerConfig( configFile: configFile, configOverwrite: optionsAsObject.configOverwrite || {}, context: optionsAsObject.context || path.dirname(configFile), - extensions: { - vue: createTypeScriptVueExtensionConfig( - optionsAsObject.extensions ? optionsAsObject.extensions.vue : undefined - ), - }, diagnosticOptions: { syntactic: false, // by default they are reported by the loader semantic: true, diff --git a/src/typescript/type-script-worker-options.ts b/src/typescript/type-script-worker-options.ts index 241ebf04..9751bd63 100644 --- a/src/typescript/type-script-worker-options.ts +++ b/src/typescript/type-script-worker-options.ts @@ -1,4 +1,3 @@ -import type { TypeScriptVueExtensionOptions } from './extension/vue/type-script-vue-extension-options'; import type { TypeScriptConfigOverwrite } from './type-script-config-overwrite'; import type { TypeScriptDiagnosticsOptions } from './type-script-diagnostics-options'; @@ -10,9 +9,6 @@ type TypeScriptWorkerOptions = { build?: boolean; mode?: 'readonly' | 'write-tsbuildinfo' | 'write-dts' | 'write-references'; diagnosticOptions?: Partial; - extensions?: { - vue?: TypeScriptVueExtensionOptions; - }; profile?: boolean; typescriptPath?: string; }; diff --git a/src/typescript/worker/lib/config.ts b/src/typescript/worker/lib/config.ts index 0ca27e6c..09545f74 100644 --- a/src/typescript/worker/lib/config.ts +++ b/src/typescript/worker/lib/config.ts @@ -9,7 +9,6 @@ import { forwardSlash } from '../../../utils/path/forward-slash'; import type { TypeScriptConfigOverwrite } from '../../type-script-config-overwrite'; import { createIssuesFromDiagnostics } from './diagnostics'; -import { extensions } from './extensions'; import { system } from './system'; import { typescript } from './typescript'; import { config } from './worker-config'; @@ -18,17 +17,12 @@ let parsedConfig: ts.ParsedCommandLine | undefined; let parseConfigDiagnostics: ts.Diagnostic[] = []; // initialize ParseConfigFileHost -let parseConfigFileHost: ts.ParseConfigFileHost = { +const parseConfigFileHost: ts.ParseConfigFileHost = { ...system, onUnRecoverableConfigFileDiagnostic: (diagnostic) => { parseConfigDiagnostics.push(diagnostic); }, }; -for (const extension of extensions) { - if (extension.extendParseConfigFileHost) { - parseConfigFileHost = extension.extendParseConfigFileHost(parseConfigFileHost); - } -} function getUserProvidedConfigOverwrite(): TypeScriptConfigOverwrite { return config.configOverwrite || {}; diff --git a/src/typescript/worker/lib/dependencies.ts b/src/typescript/worker/lib/dependencies.ts index fd50dd0a..02f8971b 100644 --- a/src/typescript/worker/lib/dependencies.ts +++ b/src/typescript/worker/lib/dependencies.ts @@ -5,7 +5,6 @@ import type * as ts from 'typescript'; import type { FilesMatch } from '../../../files-match'; import { getParsedConfig, parseConfig } from './config'; -import { extensions } from './extensions'; import { typescript } from './typescript'; import { config } from './worker-config'; @@ -16,12 +15,6 @@ export function getDependencies(force = false): FilesMatch { const parsedConfig = getParsedConfig(); dependencies = getDependenciesWorker(parsedConfig, config.context); - - for (const extension of extensions) { - if (extension.extendDependencies) { - dependencies = extension.extendDependencies(dependencies); - } - } } return dependencies; diff --git a/src/typescript/worker/lib/diagnostics.ts b/src/typescript/worker/lib/diagnostics.ts index 0e0b4f2a..f3819de8 100644 --- a/src/typescript/worker/lib/diagnostics.ts +++ b/src/typescript/worker/lib/diagnostics.ts @@ -5,7 +5,6 @@ import type * as ts from 'typescript'; import type { Issue, IssueLocation } from '../../../issue'; import { deduplicateAndSortIssues } from '../../../issue'; -import { extensions } from './extensions'; import { typescript } from './typescript'; import { config } from './worker-config'; @@ -85,15 +84,7 @@ function createIssueFromDiagnostic(diagnostic: ts.Diagnostic): Issue { } export function createIssuesFromDiagnostics(diagnostics: ts.Diagnostic[]): Issue[] { - let issues = deduplicateAndSortIssues( + return deduplicateAndSortIssues( diagnostics.map((diagnostic) => createIssueFromDiagnostic(diagnostic)) ); - - extensions.forEach((extension) => { - if (extension.extendIssues) { - issues = extension.extendIssues(issues); - } - }); - - return issues; } diff --git a/src/typescript/worker/lib/extensions.ts b/src/typescript/worker/lib/extensions.ts deleted file mode 100644 index 688450ad..00000000 --- a/src/typescript/worker/lib/extensions.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { TypeScriptExtension } from '../../extension/type-script-extension'; -import { createTypeScriptVueExtension } from '../../extension/vue/type-script-vue-extension'; - -import { config } from './worker-config'; - -const extensions: TypeScriptExtension[] = []; - -if (config.extensions?.vue?.enabled) { - extensions.push(createTypeScriptVueExtension(config.extensions.vue)); -} - -export { extensions }; diff --git a/src/typescript/worker/lib/host/compiler-host.ts b/src/typescript/worker/lib/host/compiler-host.ts index e31e76f0..3510202a 100644 --- a/src/typescript/worker/lib/host/compiler-host.ts +++ b/src/typescript/worker/lib/host/compiler-host.ts @@ -1,13 +1,12 @@ import type * as ts from 'typescript'; -import { extensions } from '../extensions'; import { system } from '../system'; import { typescript } from '../typescript'; export function createCompilerHost(parsedConfig: ts.ParsedCommandLine): ts.CompilerHost { const baseCompilerHost = typescript.createCompilerHost(parsedConfig.options); - let controlledCompilerHost: ts.CompilerHost = { + return { ...baseCompilerHost, fileExists: system.fileExists, readFile: system.readFile, @@ -15,12 +14,4 @@ export function createCompilerHost(parsedConfig: ts.ParsedCommandLine): ts.Compi getDirectories: system.getDirectories, realpath: system.realpath, }; - - extensions.forEach((extension) => { - if (extension.extendCompilerHost) { - controlledCompilerHost = extension.extendCompilerHost(controlledCompilerHost, parsedConfig); - } - }); - - return controlledCompilerHost; } diff --git a/src/typescript/worker/lib/host/watch-compiler-host.ts b/src/typescript/worker/lib/host/watch-compiler-host.ts index 794f519d..520ba118 100644 --- a/src/typescript/worker/lib/host/watch-compiler-host.ts +++ b/src/typescript/worker/lib/host/watch-compiler-host.ts @@ -1,6 +1,5 @@ import type * as ts from 'typescript'; -import { extensions } from '../extensions'; import { system } from '../system'; import { typescript } from '../typescript'; @@ -21,7 +20,7 @@ export function createWatchCompilerHost( parsedConfig.projectReferences ); - let controlledWatchCompilerHost: ts.WatchCompilerHostOfFilesAndCompilerOptions = { + return { ...baseWatchCompilerHost, createProgram( rootNames: ReadonlyArray | undefined, @@ -31,12 +30,6 @@ export function createWatchCompilerHost( configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray | undefined ): TProgram { - extensions.forEach((extension) => { - if (compilerHost && extension.extendCompilerHost) { - compilerHost = extension.extendCompilerHost(compilerHost, parsedConfig); - } - }); - return baseWatchCompilerHost.createProgram( rootNames, options, @@ -64,15 +57,4 @@ export function createWatchCompilerHost( getDirectories: system.getDirectories, realpath: system.realpath, }; - - extensions.forEach((extension) => { - if (extension.extendWatchCompilerHost) { - controlledWatchCompilerHost = extension.extendWatchCompilerHost< - TProgram, - ts.WatchCompilerHostOfFilesAndCompilerOptions - >(controlledWatchCompilerHost, parsedConfig); - } - }); - - return controlledWatchCompilerHost; } diff --git a/src/typescript/worker/lib/host/watch-solution-builder-host.ts b/src/typescript/worker/lib/host/watch-solution-builder-host.ts index b5eacf24..93cb64df 100644 --- a/src/typescript/worker/lib/host/watch-solution-builder-host.ts +++ b/src/typescript/worker/lib/host/watch-solution-builder-host.ts @@ -1,6 +1,5 @@ import type * as ts from 'typescript'; -import { extensions } from '../extensions'; import { system } from '../system'; import { typescript } from '../typescript'; @@ -23,7 +22,7 @@ export function createWatchSolutionBuilderHost = { + return { ...controlledWatchCompilerHost, reportDiagnostic(diagnostic: ts.Diagnostic): void { if (reportDiagnostic) { @@ -70,15 +69,4 @@ export function createWatchSolutionBuilderHost { - if (extension.extendWatchSolutionBuilderHost) { - controlledWatchSolutionBuilderHost = extension.extendWatchSolutionBuilderHost< - TProgram, - ts.SolutionBuilderWithWatchHost - >(controlledWatchSolutionBuilderHost, parsedConfig); - } - }); - - return controlledWatchSolutionBuilderHost; } diff --git a/test/e2e/fixtures/typescript-vue/package.json b/test/e2e/fixtures/typescript-vue/package.json deleted file mode 100644 index 1cb772c7..00000000 --- a/test/e2e/fixtures/typescript-vue/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "typescript-vue-fixture", - "version": "1.0.0", - "main": "dist/index.js", - "license": "MIT", - "devDependencies": { - "css-loader": "^3.4.2", - "qrcode.vue": "^1.7.0", - "webpack": "^5.11.0", - "webpack-cli": "^4.0.0", - "webpack-dev-server": "^3.0.0" - } -} diff --git a/test/e2e/fixtures/typescript-vue/src/App.vue b/test/e2e/fixtures/typescript-vue/src/App.vue deleted file mode 100644 index 1eec4333..00000000 --- a/test/e2e/fixtures/typescript-vue/src/App.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/test/e2e/fixtures/typescript-vue/src/component/LoggedIn.vue b/test/e2e/fixtures/typescript-vue/src/component/LoggedIn.vue deleted file mode 100644 index cccead14..00000000 --- a/test/e2e/fixtures/typescript-vue/src/component/LoggedIn.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - diff --git a/test/e2e/fixtures/typescript-vue/src/component/LoginForm.vue b/test/e2e/fixtures/typescript-vue/src/component/LoginForm.vue deleted file mode 100644 index fd227b7a..00000000 --- a/test/e2e/fixtures/typescript-vue/src/component/LoginForm.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/test/e2e/fixtures/typescript-vue/src/model/Role.ts b/test/e2e/fixtures/typescript-vue/src/model/Role.ts deleted file mode 100644 index e5fff7bd..00000000 --- a/test/e2e/fixtures/typescript-vue/src/model/Role.ts +++ /dev/null @@ -1,3 +0,0 @@ -type Role = 'admin' | 'client' | 'provider'; - -export default Role; diff --git a/test/e2e/fixtures/typescript-vue/src/model/User.ts b/test/e2e/fixtures/typescript-vue/src/model/User.ts deleted file mode 100644 index 5a0a1a62..00000000 --- a/test/e2e/fixtures/typescript-vue/src/model/User.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Role from './Role'; - -type User = { - id: string; - email: string; - role: Role; - firstName?: string; - lastName?: string; -}; - -function getUserName(user: User): string { - return [user.firstName, user.lastName].filter((name) => name !== undefined).join(' '); -} - -export default User; -export { getUserName }; diff --git a/test/e2e/fixtures/typescript-vue/tsconfig.json b/test/e2e/fixtures/typescript-vue/tsconfig.json deleted file mode 100644 index 6a8e9a4c..00000000 --- a/test/e2e/fixtures/typescript-vue/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "jsx": "preserve", - "target": "ES5", - "lib": ["ES6", "DOM"], - "baseUrl": ".", - "paths": { - "@/*": ["src/*"], - "~/*": ["src/*"] - }, - "sourceMap": true, - "importsNotUsedAsValues": "preserve" - }, - "include": [ - "src" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/test/e2e/fixtures/typescript-vue/webpack.config.js b/test/e2e/fixtures/typescript-vue/webpack.config.js deleted file mode 100644 index 97355023..00000000 --- a/test/e2e/fixtures/typescript-vue/webpack.config.js +++ /dev/null @@ -1,64 +0,0 @@ -const path = require('path'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); - -let VueLoaderPlugin; -try { - // vue-loader 15 - VueLoaderPlugin = require('vue-loader/lib/plugin'); -} catch (error) { - // vue-loader 16 - VueLoaderPlugin = require('vue-loader/dist/plugin').default; -} - -module.exports = { - entry: './src/App.vue', - output: { - filename: 'index.js', - path: path.resolve(__dirname, 'dist'), - }, - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - }, - { - test: /\.ts$/, - loader: 'ts-loader', - exclude: /node_modules/, - options: { - appendTsSuffixTo: [/\.vue$/], - transpileOnly: true, - }, - }, - { - test: /\.css$/, - loader: 'css-loader', - }, - ], - }, - resolve: { - extensions: ['.ts', '.js', '.vue', '.json'], - alias: { - '@': path.resolve(__dirname, './src'), - '~': path.resolve(__dirname, './src'), - }, - }, - plugins: [ - new VueLoaderPlugin(), - new ForkTsCheckerWebpackPlugin({ - async: false, - typescript: { - extensions: { - vue: { - enabled: true, - compiler: 'vue-template-compiler', - }, - }, - }, - }), - ], - infrastructureLogging: { - level: 'log', - }, -}; diff --git a/test/e2e/type-script-vue-extension.spec.ts b/test/e2e/type-script-vue-extension.spec.ts deleted file mode 100644 index c088ab2e..00000000 --- a/test/e2e/type-script-vue-extension.spec.ts +++ /dev/null @@ -1,117 +0,0 @@ -import path from 'path'; - -import { createWebpackDevServerDriver } from './driver/webpack-dev-server-driver'; - -describe('TypeScript Vue Extension', () => { - it.each([ - { - async: false, - compiler: 'vue-template-compiler', - typescript: '^3.8.0', - 'ts-loader': '^7.0.0', - 'vue-loader': '^15.8.3', - vue: '^2.6.11', - 'vue-template-compiler': '^2.6.11', - }, - { - async: true, - compiler: '@vue/compiler-sfc', - typescript: '^3.8.0', - 'ts-loader': '^7.0.0', - 'vue-loader': 'v16.0.0-beta.3', - vue: '^3.0.0-beta.14', - '@vue/compiler-sfc': '^3.0.0-beta.14', - }, - ])('reports semantic error for %p', async ({ async, compiler, ...dependencies }) => { - await sandbox.load(path.join(__dirname, 'fixtures/typescript-vue')); - await sandbox.install('yarn', { ...dependencies }); - await sandbox.patch('webpack.config.js', 'async: false,', `async: ${JSON.stringify(async)},`); - await sandbox.patch( - 'webpack.config.js', - "compiler: 'vue-template-compiler',", - `compiler: ${JSON.stringify(compiler)},` - ); - - if (dependencies.vue === '^2.6.11') { - await sandbox.write( - 'src/vue-shim.d.ts', - ['declare module "*.vue" {', ' import Vue from "vue";', ' export default Vue;', '}'].join( - '\n' - ) - ); - } else { - await sandbox.write('src/vue-shim.d.ts', 'declare module "*.vue";'); - } - - const driver = createWebpackDevServerDriver( - sandbox.spawn('yarn webpack serve --mode=development'), - async - ); - let errors: string[] = []; - - // first compilation is successful - await driver.waitForNoErrors(); - - // modify user model file - await sandbox.patch( - 'src/component/LoggedIn.vue', - "import User, { getUserName } from '@/model/User';", - "import User from '@/model/User';" - ); - - // next compilation should have missing function error - errors = await driver.waitForErrors(); - expect(errors).toEqual([ - [ - 'ERROR in ./src/component/LoggedIn.vue:27:23', - "TS2304: Cannot find name 'getUserName'.", - ' 25 | const user: User = this.user;', - ' 26 |', - " > 27 | return user ? getUserName(user) : '';", - ' | ^^^^^^^^^^^', - ' 28 | }', - ' 29 | },', - ' 30 | async logout() {', - ].join('\n'), - ]); - - // fix it - await sandbox.patch( - 'src/component/LoggedIn.vue', - "return user ? getUserName(user) : '';", - "return user ? `${user.firstName} ${user.lastName}` : '';" - ); - - await driver.waitForNoErrors(); - - // modify user model file again - await sandbox.patch('src/model/User.ts', ' firstName?: string;\n', ''); - - // not we should have an error about missing firstName property - errors = await driver.waitForErrors(); - expect(errors).toEqual([ - [ - 'ERROR in ./src/component/LoggedIn.vue:27:31', - "TS2339: Property 'firstName' does not exist on type 'User'.", - ' 25 | const user: User = this.user;', - ' 26 |', - " > 27 | return user ? `${user.firstName} ${user.lastName}` : '';", - ' | ^^^^^^^^^', - ' 28 | }', - ' 29 | },', - ' 30 | async logout() {', - ].join('\n'), - [ - 'ERROR in ./src/model/User.ts:11:16', - "TS2339: Property 'firstName' does not exist on type 'User'.", - ' 9 |', - ' 10 | function getUserName(user: User): string {', - " > 11 | return [user.firstName, user.lastName].filter((name) => name !== undefined).join(' ');", - ' | ^^^^^^^^^', - ' 12 | }', - ' 13 |', - ' 14 | export default User;', - ].join('\n'), - ]); - }); -}); diff --git a/test/unit/typescript/type-script-support.spec.ts b/test/unit/typescript/type-script-support.spec.ts index 5ef2e2e6..1d4eae9e 100644 --- a/test/unit/typescript/type-script-support.spec.ts +++ b/test/unit/typescript/type-script-support.spec.ts @@ -21,12 +21,6 @@ describe('typescript/type-script-support', () => { syntactic: false, }, enabled: true, - extensions: { - vue: { - enabled: false, - compiler: 'vue-template-compiler', - }, - }, memoryLimit: 2048, profile: false, typescriptPath: require.resolve('typescript'), diff --git a/test/unit/typescript/type-script-worker-config.spec.ts b/test/unit/typescript/type-script-worker-config.spec.ts index feca0137..33a84c32 100644 --- a/test/unit/typescript/type-script-worker-config.spec.ts +++ b/test/unit/typescript/type-script-worker-config.spec.ts @@ -6,7 +6,6 @@ import type webpack from 'webpack'; describe('typescript/type-scripts-worker-config', () => { let compiler: webpack.Compiler; - let createTypeScriptVueExtensionConfig: jest.Mock; const context = '/webpack/context'; const configuration: TypeScriptWorkerConfig = { @@ -23,12 +22,6 @@ describe('typescript/type-scripts-worker-config', () => { declaration: false, global: false, }, - extensions: { - vue: { - enabled: false, - compiler: 'vue-template-compiler', - }, - }, profile: false, typescriptPath: require.resolve('typescript'), }; @@ -39,13 +32,6 @@ describe('typescript/type-scripts-worker-config', () => { context, }, } as webpack.Compiler; - createTypeScriptVueExtensionConfig = jest.fn(() => ({ - enabled: false, - compiler: 'vue-template-compiler', - })); - jest.setMock('src/typescript/extension/vue/type-script-vue-extension-config', { - createTypeScriptVueExtensionConfig, - }); }); afterEach(() => { jest.resetModules(); @@ -99,23 +85,4 @@ describe('typescript/type-scripts-worker-config', () => { expect(config).toEqual(expectedConfig); }); - - it('passes vue options to the vue extension', async () => { - createTypeScriptVueExtensionConfig.mockImplementation(() => 'returned from vue extension'); - const { createTypeScriptWorkerConfig } = await import( - 'src/typescript/type-script-worker-config' - ); - - const vueOptions = { - enabled: true, - compiler: 'test-compiler', - }; - - const config = createTypeScriptWorkerConfig(compiler, { - extensions: { vue: vueOptions }, - }); - - expect(createTypeScriptVueExtensionConfig).toHaveBeenCalledWith(vueOptions); - expect(config.extensions.vue).toEqual('returned from vue extension'); - }); });