Skip to content

Commit 6c91153

Browse files
committed
Improve integration with the TypeScript provider
This allows the watcher to cater for the TypeScript build process. It also allows the provider to impact file selection.
1 parent 7ccb208 commit 6c91153

File tree

9 files changed

+110
-19
lines changed

9 files changed

+110
-19
lines changed

eslint-plugin-helper.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ function load(projectDir, overrides) {
5959
cwd: projectDir,
6060
...normalizeGlobs({
6161
extensions,
62-
files: overrides && overrides.files ? overrides.files : conf.files
62+
files: overrides && overrides.files ? overrides.files : conf.files,
63+
providers
6364
})
6465
};
6566

lib/cli.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ exports.run = async () => { // eslint-disable-line complexity
322322

323323
let globs;
324324
try {
325-
globs = normalizeGlobs({files: conf.files, ignoredByWatcher: conf.ignoredByWatcher, extensions});
325+
globs = normalizeGlobs({files: conf.files, ignoredByWatcher: conf.ignoredByWatcher, extensions, providers});
326326
} catch (error) {
327327
exit(error.message);
328328
}
@@ -411,6 +411,7 @@ exports.run = async () => { // eslint-disable-line complexity
411411
filter,
412412
globs,
413413
projectDir,
414+
providers,
414415
reporter
415416
});
416417
watcher.observeStdin(process.stdin);

lib/globs.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const globby = require('globby');
44
const ignoreByDefault = require('ignore-by-default');
55
const picomatch = require('picomatch');
66
const slash = require('slash');
7+
const {levels: providerLevels} = require('./provider-manager');
78

89
const defaultIgnorePatterns = [...ignoreByDefault.directories(), '**/node_modules'];
910
const defaultPicomatchIgnorePatterns = [
@@ -43,7 +44,7 @@ function normalizePatterns(patterns) {
4344

4445
exports.normalizePatterns = normalizePatterns;
4546

46-
function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns}) {
47+
function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns, providers}) {
4748
if (filePatterns !== undefined && (!Array.isArray(filePatterns) || filePatterns.length === 0)) {
4849
throw new Error('The \'files\' configuration must be an array containing glob patterns.');
4950
}
@@ -83,6 +84,12 @@ function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: igno
8384
ignoredByWatcherPatterns = [...defaultIgnoredByWatcherPatterns];
8485
}
8586

87+
for (const {level, main} of providers) {
88+
if (level >= providerLevels.pathRewrites) {
89+
({filePatterns, ignoredByWatcherPatterns} = main.updateGlobs({filePatterns, ignoredByWatcherPatterns}));
90+
}
91+
}
92+
8693
return {extensions, filePatterns, ignoredByWatcherPatterns};
8794
}
8895

lib/provider-manager.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ const pkg = require('../package.json');
22
const globs = require('./globs');
33

44
const levels = {
5-
ava3: 1
5+
ava3: 1,
6+
pathRewrites: 2
67
};
78

89
exports.levels = levels;
910

1011
const levelsByProtocol = {
11-
'ava-3': levels.ava3
12+
'ava-3': levels.ava3,
13+
'ava-3.2': levels.pathRewrites
1214
};
1315

1416
function load(providerModule, projectDir) {

lib/watcher.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const diff = require('lodash/difference');
66
const flatten = require('lodash/flatten');
77
const chalk = require('./chalk').get();
88
const {applyTestFileFilter, classify, getChokidarIgnorePatterns} = require('./globs');
9+
const {levels: providerLevels} = require('./provider-manager');
910

1011
function rethrowAsync(err) {
1112
// Don't swallow exceptions. Note that any
@@ -77,13 +78,14 @@ class TestDependency {
7778
}
7879

7980
class Watcher {
80-
constructor({api, filter = [], globs, projectDir, reporter}) {
81+
constructor({api, filter = [], globs, projectDir, providers, reporter}) {
8182
this.debouncer = new Debouncer(this);
8283

8384
this.clearLogOnNextRun = true;
8485
this.runVector = 0;
8586
this.previousFiles = [];
8687
this.globs = {cwd: projectDir, ...globs};
88+
this.providers = providers.filter(({level}) => level >= providerLevels.pathRewrites);
8789
this.run = (specificFiles = [], updateSnapshots = false) => {
8890
const clearLogOnNextRun = this.clearLogOnNextRun && this.runVector > 0;
8991
if (this.runVector > 0) {
@@ -190,6 +192,15 @@ class Watcher {
190192
}
191193

192194
updateTestDependencies(file, dependencies) {
195+
// Ensure the rewritten test file path is included in the dependencies,
196+
// since changes to non-rewritten paths are ignored.
197+
for (const {main} of this.providers) {
198+
const rewritten = main.resolveTestFile(file);
199+
if (!dependencies.includes(rewritten)) {
200+
dependencies = [rewritten, ...dependencies];
201+
}
202+
}
203+
193204
if (dependencies.length === 0) {
194205
this.testDependencies = this.testDependencies.filter(dep => dep.file !== file);
195206
return;
@@ -358,7 +369,7 @@ class Watcher {
358369
const {dirtyStates} = this;
359370
this.dirtyStates = {};
360371

361-
const dirtyPaths = Object.keys(dirtyStates).filter(path => {
372+
let dirtyPaths = Object.keys(dirtyStates).filter(path => {
362373
if (this.touchedFiles.has(path)) {
363374
debug('Ignoring known touched file %s', path);
364375
this.touchedFiles.delete(path);
@@ -367,6 +378,18 @@ class Watcher {
367378

368379
return true;
369380
});
381+
382+
for (const {main} of this.providers) {
383+
dirtyPaths = dirtyPaths.filter(path => {
384+
if (main.ignoreChange(path)) {
385+
debug('Ignoring changed file %s', path);
386+
return false;
387+
}
388+
389+
return true;
390+
});
391+
}
392+
370393
const dirtyHelpersAndSources = [];
371394
const dirtyTests = [];
372395
for (const filePath of dirtyPaths) {

test/api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function apiCreator(options = {}) {
2424
options.concurrency = 2;
2525
options.extensions = options.extensions || ['js'];
2626
options.experiments = {};
27-
options.globs = normalizeGlobs({files: options.files, ignoredByWatcher: options.ignoredByWatcher, extensions: options.extensions});
27+
options.globs = normalizeGlobs({files: options.files, ignoredByWatcher: options.ignoredByWatcher, extensions: options.extensions, providers: []});
2828
const instance = new Api(options);
2929

3030
return instance;

test/globs.js

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ function fixture(...args) {
1717
}
1818

1919
test('ignores relativeness in patterns', t => {
20-
const {filePatterns} = globs.normalizeGlobs({files: ['./foo.js', '!./bar'], extensions: ['js']});
20+
const {filePatterns} = globs.normalizeGlobs({files: ['./foo.js', '!./bar'], extensions: ['js'], providers: []});
2121
t.deepEqual(filePatterns, ['foo.js', '!bar']);
2222
t.end();
2323
});
2424

2525
test('isTest with defaults', t => {
2626
const options = {
2727
...globs.normalizeGlobs({
28-
extensions: ['js']
28+
extensions: ['js'],
29+
providers: []
2930
}),
3031
cwd: fixture()
3132
};
@@ -99,7 +100,8 @@ test('isTest with patterns', t => {
99100
const options = {
100101
...globs.normalizeGlobs({
101102
files: ['**/foo*.js', '**/foo*/**/*.js', '!**/fixtures', '!**/helpers'],
102-
extensions: ['js']
103+
extensions: ['js'],
104+
providers: []
103105
}),
104106
cwd: fixture()
105107
};
@@ -133,7 +135,8 @@ test('isTest (pattern starts with directory)', t => {
133135
const options = {
134136
...globs.normalizeGlobs({
135137
files: ['bar/**/*'],
136-
extensions: ['js']
138+
extensions: ['js'],
139+
providers: []
137140
}),
138141
cwd: fixture()
139142
};
@@ -163,9 +166,35 @@ test('isTest (pattern starts with directory)', t => {
163166
t.end();
164167
});
165168

169+
test('isTest after provider modifications', t => {
170+
const options = {
171+
...globs.normalizeGlobs({
172+
extensions: ['js'],
173+
providers: [{
174+
level: 2,
175+
main: {
176+
updateGlobs({filePatterns, ignoredByWatcherPatterns}) {
177+
t.true(filePatterns.length > 0);
178+
t.true(ignoredByWatcherPatterns.length > 0);
179+
return {
180+
filePatterns: ['foo.js'],
181+
ignoredByWatcherPatterns
182+
};
183+
}
184+
}
185+
}]
186+
}),
187+
cwd: fixture()
188+
};
189+
190+
t.true(globs.classify(fixture('foo.js'), options).isTest);
191+
t.false(globs.classify(fixture('bar.js'), options).isTest);
192+
t.end();
193+
});
194+
166195
test('isIgnoredByWatcher with defaults', t => {
167196
const options = {
168-
...globs.normalizeGlobs({extensions: ['js']}),
197+
...globs.normalizeGlobs({extensions: ['js'], providers: []}),
169198
cwd: fixture()
170199
};
171200

@@ -203,7 +232,8 @@ test('isIgnoredByWatcher with patterns', t => {
203232
...globs.normalizeGlobs({
204233
files: ['**/foo*'],
205234
ignoredByWatcher: ['**/bar*'],
206-
extensions: ['js']
235+
extensions: ['js'],
236+
providers: []
207237
}),
208238
cwd: fixture()
209239
};
@@ -219,7 +249,8 @@ test('isIgnoredByWatcher (pattern starts with directory)', t => {
219249
...globs.normalizeGlobs({
220250
files: ['**/foo*'],
221251
ignoredByWatcher: ['foo/**/*'],
222-
extensions: ['js']
252+
extensions: ['js'],
253+
providers: []
223254
}),
224255
cwd: fixture()
225256
};
@@ -230,6 +261,32 @@ test('isIgnoredByWatcher (pattern starts with directory)', t => {
230261
t.end();
231262
});
232263

264+
test('isIgnoredByWatcher after provider modifications', t => {
265+
const options = {
266+
...globs.normalizeGlobs({
267+
extensions: ['js'],
268+
providers: [{
269+
level: 2,
270+
main: {
271+
updateGlobs({filePatterns, ignoredByWatcherPatterns}) {
272+
t.true(filePatterns.length > 0);
273+
t.true(ignoredByWatcherPatterns.length > 0);
274+
return {
275+
filePatterns,
276+
ignoredByWatcherPatterns: ['foo.js']
277+
};
278+
}
279+
}
280+
}]
281+
}),
282+
cwd: fixture()
283+
};
284+
285+
t.true(globs.classify(fixture('foo.js'), options).isIgnoredByWatcher);
286+
t.false(globs.classify(fixture('bar.js'), options).isIgnoredByWatcher);
287+
t.end();
288+
});
289+
233290
test('findFiles finds non-ignored files (just .js)', async t => {
234291
const fixtureDir = fixture('default-patterns');
235292
process.chdir(fixtureDir);
@@ -251,7 +308,7 @@ test('findFiles finds non-ignored files (just .js)', async t => {
251308

252309
const actual = await globs.findFiles({
253310
cwd: fixtureDir,
254-
...globs.normalizeGlobs({files: ['!**/fixtures/*.*', '!**/helpers/*.*'], extensions: ['js']})
311+
...globs.normalizeGlobs({files: ['!**/fixtures/*.*', '!**/helpers/*.*'], extensions: ['js'], providers: []})
255312
});
256313
actual.sort();
257314
t.deepEqual(actual, expected);
@@ -270,7 +327,7 @@ test('findFiles finds non-ignored files (.js, .jsx)', async t => {
270327

271328
const actual = await globs.findFiles({
272329
cwd: fixtureDir,
273-
...globs.normalizeGlobs({files: ['!**/fixtures/*', '!**/helpers/*'], extensions: ['js', 'jsx']})
330+
...globs.normalizeGlobs({files: ['!**/fixtures/*', '!**/helpers/*'], extensions: ['js', 'jsx'], providers: []})
274331
});
275332
actual.sort();
276333
t.deepEqual(actual, expected);

test/helper/report.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ const run = (type, reporter, match = []) => {
102102
pattern = '*.ts';
103103
}
104104

105-
options.globs = normalizeGlobs({extensions: options.extensions});
105+
options.globs = normalizeGlobs({extensions: options.extensions, providers: []});
106106

107107
const api = createApi(options);
108108
api.on('run', plan => reporter.startRun(plan));

test/watcher.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ group('chokidar', (beforeEach, test, group) => {
145145
Subject = proxyWatcher();
146146
});
147147

148-
const start = ignoredByWatcher => new Subject({reporter, api, filter: [], globs: normalizeGlobs({files, ignoredByWatcher, extensions: ['js']}), projectDir: process.cwd()});
148+
const start = ignoredByWatcher => new Subject({reporter, api, filter: [], globs: normalizeGlobs({files, ignoredByWatcher, extensions: ['js'], providers: []}), projectDir: process.cwd(), providers: []});
149149

150150
const emitChokidar = (event, path) => {
151151
chokidarEmitter.emit('all', event, path);

0 commit comments

Comments
 (0)