Throw when more than one custom factory is applicable
diff --git a/lib/src/custom_watcher_factory.dart b/lib/src/custom_watcher_factory.dart
index ffac06b..b7f81fa 100644
--- a/lib/src/custom_watcher_factory.dart
+++ b/lib/src/custom_watcher_factory.dart
@@ -10,23 +10,20 @@
/// Tries to create a [DirectoryWatcher] for the provided path.
///
- /// Should return `null` if the path is not supported by this factory.
+ /// Returns `null` if the path is not supported by this factory.
DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay});
/// Tries to create a [FileWatcher] for the provided path.
///
- /// Should return `null` if the path is not supported by this factory.
+ /// Returns `null` if the path is not supported by this factory.
FileWatcher createFileWatcher(String path, {Duration pollingDelay});
}
/// Registers a custom watcher.
///
-/// It's only allowed to register a watcher once per [id]. The [supportsPath]
-/// will be called to determine if the [createWatcher] should be used instead of
-/// the built-in watchers.
-///
-/// Note that we will try [CustomWatcherFactory] one by one in the order they
-/// were registered.
+/// It's only allowed to register a watcher factory once per [id] and at most
+/// one factory should apply to any given file (creating a [Watcher] will fail
+/// otherwise).
void registerCustomWatcherFactory(CustomWatcherFactory customFactory) {
if (_customWatcherFactories.containsKey(customFactory.id)) {
throw ArgumentError('A custom watcher with id `${customFactory.id}` '
@@ -35,8 +32,48 @@
_customWatcherFactories[customFactory.id] = customFactory;
}
-/// Unregisters a custom watcher and returns it (returns `null` if it was never
-/// registered).
+/// Tries to create a custom [DirectoryWatcher] and returns it.
+///
+/// Returns `null` if no custom watcher was applicable and throws a [StateError]
+/// if more than one was.
+DirectoryWatcher createCustomDirectoryWatcher(String path,
+ {Duration pollingDelay}) {
+ DirectoryWatcher customWatcher;
+ String customFactoryId;
+ for (var watcherFactory in customWatcherFactories) {
+ if (customWatcher != null) {
+ throw StateError('Two `CustomWatcherFactory`s applicable: '
+ '`$customFactoryId` and `${watcherFactory.id}` for `$path`');
+ }
+ customWatcher =
+ watcherFactory.createDirectoryWatcher(path, pollingDelay: pollingDelay);
+ customFactoryId = watcherFactory.id;
+ }
+ return customWatcher;
+}
+
+/// Tries to create a custom [FileWatcher] and returns it.
+///
+/// Returns `null` if no custom watcher was applicable and throws a [StateError]
+/// if more than one was.
+FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) {
+ FileWatcher customWatcher;
+ String customFactoryId;
+ for (var watcherFactory in customWatcherFactories) {
+ if (customWatcher != null) {
+ throw StateError('Two `CustomWatcherFactory`s applicable: '
+ '`$customFactoryId` and `${watcherFactory.id}` for `$path`');
+ }
+ customWatcher =
+ watcherFactory.createFileWatcher(path, pollingDelay: pollingDelay);
+ customFactoryId = watcherFactory.id;
+ }
+ return customWatcher;
+}
+
+/// Unregisters a custom watcher and returns it.
+///
+/// Returns `null` if the id was never registered.
CustomWatcherFactory unregisterCustomWatcherFactory(String id) =>
_customWatcherFactories.remove(id);
diff --git a/lib/src/directory_watcher.dart b/lib/src/directory_watcher.dart
index 858d020..3fe5004 100644
--- a/lib/src/directory_watcher.dart
+++ b/lib/src/directory_watcher.dart
@@ -30,14 +30,9 @@
/// watchers.
factory DirectoryWatcher(String directory, {Duration pollingDelay}) {
if (FileSystemEntity.isWatchSupported) {
- for (var custom in customWatcherFactories) {
- var watcher = custom.createDirectoryWatcher(directory,
- pollingDelay: pollingDelay);
- if (watcher != null) {
- return watcher;
- }
- }
-
+ var customWatcher =
+ createCustomDirectoryWatcher(directory, pollingDelay: pollingDelay);
+ if (customWatcher != null) return customWatcher;
if (Platform.isLinux) return LinuxDirectoryWatcher(directory);
if (Platform.isMacOS) return MacOSDirectoryWatcher(directory);
if (Platform.isWindows) return WindowsDirectoryWatcher(directory);
diff --git a/lib/src/file_watcher.dart b/lib/src/file_watcher.dart
index 0b7afc7..c41e5e6 100644
--- a/lib/src/file_watcher.dart
+++ b/lib/src/file_watcher.dart
@@ -30,12 +30,9 @@
/// and higher CPU usage. Defaults to one second. Ignored for non-polling
/// watchers.
factory FileWatcher(String file, {Duration pollingDelay}) {
- for (var custom in customWatcherFactories) {
- var watcher = custom.createFileWatcher(file, pollingDelay: pollingDelay);
- if (watcher != null) {
- return watcher;
- }
- }
+ var customWatcher =
+ createCustomFileWatcher(file, pollingDelay: pollingDelay);
+ if (customWatcher != null) return customWatcher;
// [File.watch] doesn't work on Windows, but
// [FileSystemEntity.isWatchSupported] is still true because directory
diff --git a/test/custom_watcher_factory_test.dart b/test/custom_watcher_factory_test.dart
index 784769c..6d9ed40 100644
--- a/test/custom_watcher_factory_test.dart
+++ b/test/custom_watcher_factory_test.dart
@@ -1,19 +1,19 @@
import 'dart:async';
-import 'dart:io';
import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
void main() {
_MemFs memFs;
+ final defaultFactoryId = 'MemFs';
setUp(() {
memFs = _MemFs();
- registerCustomWatcherFactory(_MemFsWatcherFactory(memFs));
+ registerCustomWatcherFactory(_MemFsWatcherFactory(defaultFactoryId, memFs));
});
tearDown(() async {
- unregisterCustomWatcherFactory('MemFs');
+ unregisterCustomWatcherFactory(defaultFactoryId);
});
test('notifes for files', () async {
@@ -43,8 +43,7 @@
});
test('unregister works', () async {
- var memFactory = _MemFsWatcherFactory(memFs);
- unregisterCustomWatcherFactory(memFactory.id);
+ unregisterCustomWatcherFactory(defaultFactoryId);
var events = <WatchEvent>[];
var watcher = FileWatcher('file.txt');
@@ -59,9 +58,19 @@
});
test('registering twice throws', () async {
- expect(() => registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)),
+ expect(
+ () => registerCustomWatcherFactory(
+ _MemFsWatcherFactory(defaultFactoryId, memFs)),
throwsA(isA<ArgumentError>()));
});
+
+ test('finding two applicable factories throws', () async {
+ // Note that _MemFsWatcherFactory always returns a watcher, so having two
+ // will always produce a conflict.
+ registerCustomWatcherFactory(_MemFsWatcherFactory('Different id', memFs));
+ expect(() => FileWatcher('file.txt'), throwsA(isA<StateError>()));
+ expect(() => DirectoryWatcher('dir'), throwsA(isA<StateError>()));
+ });
}
class _MemFs {
@@ -115,11 +124,9 @@
}
class _MemFsWatcherFactory implements CustomWatcherFactory {
+ final String id;
final _MemFs _memFs;
- _MemFsWatcherFactory(this._memFs);
-
- @override
- String get id => 'MemFs';
+ _MemFsWatcherFactory(this.id, this._memFs);
@override
DirectoryWatcher createDirectoryWatcher(String path,