Skip to content

Commit 7e74e05

Browse files
authored
Merge pull request #268 from phryneas/fix-linter-tests
improve generation of diagnostics, fix linter tests
2 parents 1d70a8c + 9b73b3a commit 7e74e05

File tree

3 files changed

+117
-10
lines changed

3 files changed

+117
-10
lines changed

src/patchTypescript.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// tslint:disable-next-line:no-implicit-dependencies
2+
import * as ts from 'typescript'; // Imported for types alone
3+
4+
export interface TypeScriptPatchConfig {
5+
/**
6+
* Ususally, the compilerHost created with typescript.createWatchCompilerHost will bail out of diagnostics collection if there has been any syntactic error.
7+
* (see [`emitFilesAndReportErrors`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L141) )
8+
* If this plugin is running with `checkSyntacticErrors: false`, this might lead to situations where no syntactic errors are reported within webpack
9+
* (because the file causing a syntactic error might not get processed by ts-loader), but there are semantic errors that would be missed due to this behavior.
10+
* This ensures that the compilerHost always assumes that there were no syntactic errors to be found and continues to check for semantic errors.
11+
*/
12+
skipGetSyntacticDiagnostics: boolean;
13+
}
14+
15+
/**
16+
* While it is often possible to pass a wrapped or modified copy of `typescript` or `typescript.sys` as a function argument to override/extend some typescript-internal behavior,
17+
* sometimes the typescript-internal code ignores these passed objects and directly references the internal `typescript` object reference.
18+
* In these situations, the only way of consistently overriding some behavior is to directly replace methods on the `typescript` object.
19+
*
20+
* So beware, this method directly modifies the passed `typescript` object!
21+
* @param typescript TypeScript instance to patch
22+
* @param config
23+
*/
24+
export function patchTypescript(
25+
typescript: typeof ts,
26+
config: TypeScriptPatchConfig
27+
) {
28+
if (config.skipGetSyntacticDiagnostics) {
29+
patchSkipGetSyntacticDiagnostics(typescript);
30+
}
31+
}
32+
33+
/**
34+
* Overrides the [`typescript.createEmitAndSemanticDiagnosticsBuilderProgram`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/builder.ts#L1176)
35+
* method to return a `ts.Program` instance that does not emit syntactic errors,
36+
* to prevent the [`typescript.createWatchCompilerHost`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L333)
37+
* method from bailing during diagnostic collection in the [`emitFilesAndReportErrors`](https://github.com/Microsoft/TypeScript/blob/89386ddda7dafc63cb35560e05412487f47cc267/src/compiler/watch.ts#L141) callback.
38+
*
39+
* See the description of TypeScriptPatchConfig.skipGetSyntacticDiagnostics and
40+
* [this github discussion](https://github.com/Realytics/fork-ts-checker-webpack-plugin/issues/257#issuecomment-485414182)
41+
* for further information on this problem & solution.
42+
*/
43+
function patchSkipGetSyntacticDiagnostics(typescript: typeof ts) {
44+
const {
45+
createEmitAndSemanticDiagnosticsBuilderProgram: originalCreateEmitAndSemanticDiagnosticsBuilderProgram
46+
} = typescript;
47+
48+
const patchedMethods: Pick<
49+
typeof ts,
50+
'createEmitAndSemanticDiagnosticsBuilderProgram'
51+
> = {
52+
createEmitAndSemanticDiagnosticsBuilderProgram(...args: any[]) {
53+
const program = originalCreateEmitAndSemanticDiagnosticsBuilderProgram.apply(
54+
typescript,
55+
args as any
56+
);
57+
program.getSyntacticDiagnostics = () => [];
58+
return program;
59+
}
60+
};
61+
62+
// directly patch the typescript object!
63+
Object.assign(typescript, patchedMethods);
64+
}

src/service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from './NormalizedMessageFactories';
1414
import { RpcProvider } from 'worker-rpc';
1515
import { RunPayload, RunResult, RUN } from './RpcTypes';
16+
import { TypeScriptPatchConfig, patchTypescript } from './patchTypescript';
1617

1718
const rpc = new RpcProvider(message => {
1819
try {
@@ -25,6 +26,13 @@ const rpc = new RpcProvider(message => {
2526
process.on('message', message => rpc.dispatch(message));
2627

2728
const typescript: typeof ts = require(process.env.TYPESCRIPT_PATH!);
29+
const patchConfig: TypeScriptPatchConfig = {
30+
skipGetSyntacticDiagnostics:
31+
process.env.USE_INCREMENTAL_API === 'true' &&
32+
process.env.CHECK_SYNTACTIC_ERRORS !== 'true'
33+
};
34+
35+
patchTypescript(typescript, patchConfig);
2836

2937
// message factories
3038
export const createNormalizedMessageFromDiagnostic = makeCreateNormalizedMessageFromDiagnostic(

test/integration/index.spec.js

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ function makeCommonTests(useTypescriptIncrementalApi) {
2323
this.timeout(60000);
2424
var plugin;
2525

26+
const overrideOptions = { useTypescriptIncrementalApi };
27+
2628
function createCompiler(
2729
options,
2830
happyPackMode,
2931
entryPoint = './src/index.ts'
3032
) {
3133
options = options || {};
32-
options.useTypescriptIncrementalApi = useTypescriptIncrementalApi;
34+
options = { ...options, ...overrideOptions };
3335
var compiler = helpers.createCompiler(options, happyPackMode, entryPoint);
3436
plugin = compiler.plugin;
3537
return compiler.webpack;
@@ -80,17 +82,42 @@ function makeCommonTests(useTypescriptIncrementalApi) {
8082
expect(plugin.watch).to.deep.equal(['/test']);
8183
});
8284

85+
it('should find lint warnings', function(callback) {
86+
const fileName = 'lintingError2';
87+
helpers.testLintAutoFixTest(
88+
callback,
89+
fileName,
90+
{
91+
tslint: path.resolve(__dirname, './project/tslint.json'),
92+
ignoreLintWarnings: false,
93+
...overrideOptions
94+
},
95+
(err, stats) => {
96+
expect(
97+
stats.compilation.warnings.filter(warning =>
98+
warning.message.includes('missing whitespace')
99+
).length
100+
).to.be.greaterThan(0);
101+
}
102+
);
103+
});
104+
83105
it('should not print warnings when ignoreLintWarnings passed as option', function(callback) {
84106
const fileName = 'lintingError2';
85107
helpers.testLintAutoFixTest(
86108
callback,
87109
fileName,
88110
{
89-
tslint: true,
90-
ignoreLintWarnings: true
111+
tslint: path.resolve(__dirname, './project/tslint.json'),
112+
ignoreLintWarnings: true,
113+
...overrideOptions
91114
},
92115
(err, stats) => {
93-
expect(stats.compilation.warnings.length).to.be.eq(0);
116+
expect(
117+
stats.compilation.warnings.filter(warning =>
118+
warning.message.includes('missing whitespace')
119+
).length
120+
).to.be.equal(0);
94121
}
95122
);
96123
});
@@ -101,11 +128,16 @@ function makeCommonTests(useTypescriptIncrementalApi) {
101128
callback,
102129
fileName,
103130
{
104-
tslint: true,
105-
ignoreLintWarnings: true
131+
tslint: path.resolve(__dirname, './project/tslint.json'),
132+
ignoreLintWarnings: true,
133+
...overrideOptions
106134
},
107135
(err, stats) => {
108-
expect(stats.compilation.errors.length).to.be.eq(0);
136+
expect(
137+
stats.compilation.errors.filter(error =>
138+
error.message.includes('missing whitespace')
139+
).length
140+
).to.be.equals(0);
109141
}
110142
);
111143
});
@@ -157,7 +189,8 @@ function makeCommonTests(useTypescriptIncrementalApi) {
157189
{
158190
tslintAutoFix: true,
159191
tslint: path.resolve(__dirname, './project/tslint.autofix.json'),
160-
tsconfig: false
192+
tsconfig: false,
193+
...overrideOptions
161194
},
162195
(err, stats, formattedFileContents) => {
163196
expect(stats.compilation.warnings.length).to.be.eq(0);
@@ -179,7 +212,8 @@ function makeCommonTests(useTypescriptIncrementalApi) {
179212
callback,
180213
fileName,
181214
{
182-
tslint: true
215+
tslint: true,
216+
...overrideOptions
183217
},
184218
(err, stats) => {
185219
expect(stats.compilation.warnings.length).to.be.eq(7);
@@ -362,7 +396,8 @@ function makeCommonTests(useTypescriptIncrementalApi) {
362396
helpers.testLintHierarchicalConfigs(
363397
callback,
364398
{
365-
tslint: true
399+
tslint: true,
400+
...overrideOptions
366401
},
367402
(err, stats) => {
368403
/*

0 commit comments

Comments
 (0)