Skip to content

Commit aa4a97e

Browse files
authored
Merge pull request #169 from liangchunn/chore/lint
Support linting + formatting with pre-commit hook
2 parents 237b1fd + 9f90748 commit aa4a97e

34 files changed

+1892
-1003
lines changed

.eslintrc.json

+12-18
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
{
2-
"env": {
3-
"node": true
4-
},
5-
"extends": "eslint:recommended",
6-
"rules": {
7-
"indent": [
8-
"error",
9-
2
10-
],
11-
"quotes": [
12-
"error",
13-
"single"
14-
],
15-
"semi": [
16-
"error",
17-
"always"
18-
]
2+
"parserOptions": {
3+
"ecmaVersion": 6,
4+
"ecmaFeatures": {
5+
"experimentalObjectRestSpread": true
196
}
20-
}
7+
},
8+
"env": {
9+
"node": true,
10+
"mocha": true,
11+
"es6": true
12+
},
13+
"extends": "eslint:recommended"
14+
}

.prettierrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"singleQuote": true,
3+
"semi": true,
4+
"tabWidth": 2,
5+
"useTabs": false,
6+
"printWidth": 80
7+
}

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ install:
55
- yarn install
66
- yarn build
77
- yarn add $WEBPACK $TSLOADER $VUELOADER -D
8+
- yarn lint
89
env:
910
- WEBPACK=webpack@^4.0.0 TSLOADER=ts-loader@^4.3.0 VUELOADER=vue-loader@^15.2.4
1011
- WEBPACK=webpack@^3.10.0 TSLOADER=ts-loader@^3.4.0 VUELOADER=vue-loader@^13.5.0

package.json

+28-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"test": "npm run build && npm run test:unit && npm run test:integration",
1515
"test:watch": "mocha -R spec --watch ./test/unit",
1616
"test:coverage": "rimraf coverage && istanbul cover -root lib --include-all-sources mocha -- -R spec ./test/unit ./test/integration",
17-
"lint": "eslint ./lib ./test",
18-
"lint:fix": "eslint ./lib ./test --fix"
17+
"lint": "tslint --project src/tsconfig.json && eslint ./test",
18+
"lint:fix": "tslint --project src/tsconfig.json --fix && eslint ./test --fix"
1919
},
2020
"repository": {
2121
"url": "https://github.com/Realytics/fork-ts-checker-webpack-plugin.git",
@@ -61,15 +61,19 @@
6161
"@types/webpack": "^4.4.9",
6262
"chai": "^3.5.0",
6363
"css-loader": "^0.28.7",
64-
"eslint": "^3.19.0",
64+
"eslint": "^5.7.0",
65+
"husky": "^1.1.2",
6566
"istanbul": "^0.4.5",
67+
"lint-staged": "^7.3.0",
6668
"mocha": "^3.4.1",
6769
"mock-fs": "^4.3.0",
6870
"mock-require": "^2.0.2",
71+
"prettier": "^1.14.3",
6972
"rimraf": "^2.5.4",
7073
"sinon": "^2.3.1",
7174
"ts-loader": "4.3.0",
72-
"tslint": "^5.0.0",
75+
"tslint": "^5.11.0",
76+
"tslint-config-prettier": "^1.15.0",
7377
"typescript": "^3.0.1",
7478
"vue": "^2.5.16",
7579
"vue-class-component": "^6.1.1",
@@ -93,5 +97,25 @@
9397
"minimatch": "^3.0.4",
9498
"resolve": "^1.5.0",
9599
"tapable": "^1.0.0"
100+
},
101+
"husky": {
102+
"hooks": {
103+
"pre-commit": "lint-staged"
104+
}
105+
},
106+
"lint-staged": {
107+
"concurrent": false,
108+
"linters": {
109+
"*.js": [
110+
"eslint --fix"
111+
],
112+
"*.ts": [
113+
"tslint --fix"
114+
],
115+
"*.{js,ts}": [
116+
"prettier --write",
117+
"git add"
118+
]
119+
}
96120
}
97121
}

src/CancellationToken.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ export class CancellationToken {
1515
lastCancellationCheckTime: number;
1616
constructor(cancellationFileName: string, isCancelled: boolean) {
1717
this.isCancelled = !!isCancelled;
18-
this.cancellationFileName = cancellationFileName || crypto.randomBytes(64).toString('hex');
18+
this.cancellationFileName =
19+
cancellationFileName || crypto.randomBytes(64).toString('hex');
1920
this.lastCancellationCheckTime = 0;
2021
}
2122

2223
static createFromJSON(json: CancellationTokenData) {
23-
return new CancellationToken(
24-
json.cancellationFileName,
25-
json.isCancelled
26-
);
24+
return new CancellationToken(json.cancellationFileName, json.isCancelled);
2725
}
2826

2927
toJSON() {

src/FilesRegister.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface DataShape {
77
}
88

99
export class FilesRegister {
10-
files: { [filePath: string]: { mtime: number; data: DataShape; }};
10+
files: { [filePath: string]: { mtime: number; data: DataShape } };
1111
dataFactory: (_data?: any) => DataShape; // It doesn't seem that the _data parameter is ever used?
1212

1313
constructor(dataFactory: (_data?: any) => DataShape) {
@@ -74,4 +74,3 @@ export class FilesRegister {
7474
}
7575
}
7676
}
77-

src/FilesWatcher.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ export class FilesWatcher {
2424
}
2525

2626
this.watchers = this.watchPaths.map((watchPath: string) => {
27-
return chokidar.watch(
28-
watchPath,
29-
{ persistent: true, alwaysStat: true }
30-
)
27+
return chokidar
28+
.watch(watchPath, { persistent: true, alwaysStat: true })
3129
.on('change', (filePath: string, stats: any) => {
3230
if (this.isFileSupported(filePath)) {
3331
(this.listeners['change'] || []).forEach(changeListener => {
@@ -67,7 +65,9 @@ export class FilesWatcher {
6765

6866
off(event: string, listener: Function) {
6967
if (this.listeners[event]) {
70-
this.listeners[event] = this.listeners[event].filter(oldListener => oldListener !== listener);
68+
this.listeners[event] = this.listeners[event].filter(
69+
oldListener => oldListener !== listener
70+
);
7171
}
7272
}
7373
}

src/IncrementalChecker.ts

+85-33
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,19 @@ export class IncrementalChecker {
6161

6262
// it's shared between compilations
6363
this.files = new FilesRegister(() => ({
64-
// data shape
65-
source: undefined,
66-
linted: false,
67-
lints: []
64+
// data shape
65+
source: undefined,
66+
linted: false,
67+
lints: []
6868
}));
6969
}
7070

7171
static loadProgramConfig(configFile: string) {
7272
return ts.parseJsonConfigFileContent(
7373
// Regardless of the setting in the tsconfig.json we want isolatedModules to be false
74-
Object.assign(ts.readConfigFile(configFile, ts.sys.readFile).config, { isolatedModules: false }),
74+
Object.assign(ts.readConfigFile(configFile, ts.sys.readFile).config, {
75+
isolatedModules: false
76+
}),
7577
ts.sys,
7678
path.dirname(configFile)
7779
);
@@ -80,7 +82,9 @@ export class IncrementalChecker {
8082
static loadLinterConfig(configFile: string): ConfigurationFile {
8183
const tslint = require('tslint');
8284

83-
return tslint.Configuration.loadConfigurationFromPath(configFile) as ConfigurationFile;
85+
return tslint.Configuration.loadConfigurationFromPath(
86+
configFile
87+
) as ConfigurationFile;
8488
}
8589

8690
static createProgram(
@@ -107,7 +111,7 @@ export class IncrementalChecker {
107111

108112
// get source file only if there is no source in files register
109113
if (!files.has(filePath) || !files.getData(filePath).source) {
110-
files.mutateData(filePath, (data) => {
114+
files.mutateData(filePath, data => {
111115
data.source = realGetSourceFile(filePath, languageVersion, onError);
112116
});
113117
}
@@ -129,13 +133,21 @@ export class IncrementalChecker {
129133
return new tslint.Linter({ fix: false }, program);
130134
}
131135

132-
static isFileExcluded(filePath: string, linterExclusions: minimatch.IMinimatch[]): boolean {
133-
return endsWith(filePath, '.d.ts') || linterExclusions.some(matcher => matcher.match(filePath));
136+
static isFileExcluded(
137+
filePath: string,
138+
linterExclusions: minimatch.IMinimatch[]
139+
): boolean {
140+
return (
141+
endsWith(filePath, '.d.ts') ||
142+
linterExclusions.some(matcher => matcher.match(filePath))
143+
);
134144
}
135145

136146
nextIteration() {
137147
if (!this.watcher) {
138-
const watchExtensions = this.vue ? ['.ts', '.tsx', '.vue'] : ['.ts', '.tsx'];
148+
const watchExtensions = this.vue
149+
? ['.ts', '.tsx', '.vue']
150+
: ['.ts', '.tsx'];
139151
this.watcher = new FilesWatcher(this.watchPaths, watchExtensions);
140152

141153
// connect watcher with register
@@ -150,13 +162,20 @@ export class IncrementalChecker {
150162
}
151163

152164
if (!this.linterConfig && this.linterConfigFile) {
153-
this.linterConfig = IncrementalChecker.loadLinterConfig(this.linterConfigFile);
154-
155-
if (this.linterConfig.linterOptions && this.linterConfig.linterOptions.exclude) {
165+
this.linterConfig = IncrementalChecker.loadLinterConfig(
166+
this.linterConfigFile
167+
);
168+
169+
if (
170+
this.linterConfig.linterOptions &&
171+
this.linterConfig.linterOptions.exclude
172+
) {
156173
// Pre-build minimatch patterns to avoid additional overhead later on.
157174
// Note: Resolving the path is required to properly match against the full file paths,
158175
// and also deals with potential cross-platform problems regarding path separators.
159-
this.linterExclusions = this.linterConfig.linterOptions.exclude.map(pattern => new minimatch.Minimatch(path.resolve(pattern)));
176+
this.linterExclusions = this.linterConfig.linterOptions.exclude.map(
177+
pattern => new minimatch.Minimatch(path.resolve(pattern))
178+
);
160179
}
161180
}
162181

@@ -168,7 +187,9 @@ export class IncrementalChecker {
168187
}
169188

170189
loadVueProgram() {
171-
this.programConfig = this.programConfig || VueProgram.loadProgramConfig(this.programConfigFile);
190+
this.programConfig =
191+
this.programConfig ||
192+
VueProgram.loadProgramConfig(this.programConfigFile);
172193

173194
return VueProgram.createProgram(
174195
this.programConfig,
@@ -180,9 +201,16 @@ export class IncrementalChecker {
180201
}
181202

182203
loadDefaultProgram() {
183-
this.programConfig = this.programConfig || IncrementalChecker.loadProgramConfig(this.programConfigFile);
204+
this.programConfig =
205+
this.programConfig ||
206+
IncrementalChecker.loadProgramConfig(this.programConfigFile);
184207

185-
return IncrementalChecker.createProgram(this.programConfig, this.files, this.watcher, this.program);
208+
return IncrementalChecker.createProgram(
209+
this.programConfig,
210+
this.files,
211+
this.watcher,
212+
this.program
213+
);
186214
}
187215

188216
hasLinter() {
@@ -195,18 +223,30 @@ export class IncrementalChecker {
195223
const filesToCheck = this.program.getSourceFiles();
196224

197225
// calculate subset of work to do
198-
const workSet = new WorkSet(filesToCheck, this.workNumber, this.workDivision);
226+
const workSet = new WorkSet(
227+
filesToCheck,
228+
this.workNumber,
229+
this.workDivision
230+
);
199231

200232
// check given work set
201233
workSet.forEach(sourceFile => {
202234
if (cancellationToken) {
203235
cancellationToken.throwIfCancellationRequested();
204236
}
205237

206-
const diagnosticsToRegister: ReadonlyArray<ts.Diagnostic> = this.checkSyntacticErrors
238+
const diagnosticsToRegister: ReadonlyArray<ts.Diagnostic> = this
239+
.checkSyntacticErrors
207240
? []
208-
.concat(this.program.getSemanticDiagnostics(sourceFile, cancellationToken))
209-
.concat(this.program.getSyntacticDiagnostics(sourceFile, cancellationToken))
241+
.concat(
242+
this.program.getSemanticDiagnostics(sourceFile, cancellationToken)
243+
)
244+
.concat(
245+
this.program.getSyntacticDiagnostics(
246+
sourceFile,
247+
cancellationToken
248+
)
249+
)
210250
: this.program.getSemanticDiagnostics(sourceFile, cancellationToken);
211251

212252
diagnostics.push.apply(diagnostics, diagnosticsToRegister);
@@ -224,12 +264,20 @@ export class IncrementalChecker {
224264
}
225265

226266
// select files to lint
227-
const filesToLint = this.files.keys().filter(filePath =>
228-
!this.files.getData(filePath).linted && !IncrementalChecker.isFileExcluded(filePath, this.linterExclusions)
229-
);
267+
const filesToLint = this.files
268+
.keys()
269+
.filter(
270+
filePath =>
271+
!this.files.getData(filePath).linted &&
272+
!IncrementalChecker.isFileExcluded(filePath, this.linterExclusions)
273+
);
230274

231275
// calculate subset of work to do
232-
const workSet = new WorkSet(filesToLint, this.workNumber, this.workDivision);
276+
const workSet = new WorkSet(
277+
filesToLint,
278+
this.workNumber,
279+
this.workDivision
280+
);
233281

234282
// lint given work set
235283
workSet.forEach(fileName => {
@@ -239,11 +287,11 @@ export class IncrementalChecker {
239287
this.linter.lint(fileName, undefined, this.linterConfig);
240288
} catch (e) {
241289
if (
242-
fs.existsSync(fileName) &&
243-
// check the error type due to file system lag
244-
!(e instanceof Error) &&
245-
!(e.constructor.name === 'FatalError') &&
246-
!(e.message && e.message.trim().startsWith("Invalid source file"))
290+
fs.existsSync(fileName) &&
291+
// check the error type due to file system lag
292+
!(e instanceof Error) &&
293+
!(e.constructor.name === 'FatalError') &&
294+
!(e.message && e.message.trim().startsWith('Invalid source file'))
247295
) {
248296
// it's not because file doesn't exist - throw error
249297
throw e;
@@ -269,9 +317,13 @@ export class IncrementalChecker {
269317
});
270318

271319
// get all lints
272-
const lints = this.files.keys().reduce((innerLints, filePath) =>
273-
innerLints.concat(this.files.getData(filePath).lints),
274-
[]);
320+
const lints = this.files
321+
.keys()
322+
.reduce(
323+
(innerLints, filePath) =>
324+
innerLints.concat(this.files.getData(filePath).lints),
325+
[]
326+
);
275327

276328
// normalize and deduplicate lints
277329
return NormalizedMessage.deduplicate(

src/Message.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NormalizedMessage } from './NormalizedMessage';
22

33
export interface Message {
4-
diagnostics: NormalizedMessage[];
5-
lints: NormalizedMessage[];
4+
diagnostics: NormalizedMessage[];
5+
lints: NormalizedMessage[];
66
}

0 commit comments

Comments
 (0)