This repository has been archived by the owner on Sep 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Core): Start work on a MissingProviderError, with better error m…
…essages. Added a simple test (passes), and a complex test (skipped, does not pass). In dev-mode we will start tracking the chain of failed lookups and give a better error message, i.e. "No provider found for B: A -> B". Work towards #434. PiperOrigin-RevId: 184594151
- Loading branch information
1 parent
ca84a28
commit d97324b
Showing
6 changed files
with
142 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
@TestOn('browser') | ||
import 'package:angular/angular.dart'; | ||
import 'package:angular/src/di/injector/injector.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
import 'missing_provider_test.template.dart' as ng; | ||
|
||
void main() { | ||
ng.initReflector(); | ||
|
||
test('should throw an error for a single missing token', () { | ||
final nullInjector = const Injector.empty(); | ||
expect( | ||
() => nullInjector.get(A), | ||
throwsA(predicate((e) => '$e'.contains('No provider found for $A'))), | ||
); | ||
}); | ||
|
||
test('should throw a better error for a path of missing tokens', () { | ||
final injectorWithAB = new Injector.slowReflective([A]); | ||
expect( | ||
() => injectorWithAB.get(A), | ||
throwsA( | ||
predicate((e) => '$e'.contains('No provider found for $B: $A -> $B')), | ||
), | ||
); | ||
}, skip: 'Not yet supported: We need to track the provider chain.'); | ||
} | ||
|
||
@Injectable() | ||
class A { | ||
A(B b); | ||
} | ||
|
||
@Injectable() | ||
class B {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import 'package:angular/src/facade/lang.dart'; | ||
|
||
import 'injector/injector.dart'; | ||
|
||
/// A list representing tokens not found in development mode. | ||
/// | ||
/// In production mode, this is always `null`, and should be ignored. | ||
List<Object> devModeTokensNotResolvable; | ||
|
||
/// An error thrown when a token is not found when using an [Injector]. | ||
/// | ||
/// **NOTE**: This error is only guaranteed to be thrown in development mode | ||
/// (i.e. when `assert` is enabled). Otherwise a generic error is thrown with | ||
/// less information (but better performance and lower code-size). | ||
class MissingProviderError extends Error { | ||
/// Creates an error representing a miss on [token] looked up on [injector]. | ||
static Error create(Injector injector, Object token) { | ||
if (assertionsEnabled()) { | ||
_findMissingTokenPath(injector, token); | ||
return new MissingProviderError._(devModeTokensNotResolvable); | ||
} | ||
return new ArgumentError('No provider found for $token.'); | ||
} | ||
|
||
static void _findMissingTokenPath(Injector injector, Object token) { | ||
// TODO(matanl): Actually implement the rest of the missing path. | ||
// i.e. Leaf -> Parent -> Root, not just Leaf. | ||
devModeTokensNotResolvable = [token]; | ||
} | ||
|
||
/// A list of tokens that was attempted, in order, that resulted in an error. | ||
/// | ||
/// For example: `[Leaf, Parent, Root]`, where `Root` was the root service | ||
/// that was missing, looked up via a dependency on `Parent`, which was a | ||
/// dependency of `Leaf`, the actual token requested via `get(Leaf)`. | ||
final List<Object> tokens; | ||
|
||
MissingProviderError._(this.tokens); | ||
|
||
@override | ||
String toString() => | ||
// Example: No provider found for Leaf: Leaf -> Parent -> Root. | ||
tokens.length == 1 | ||
? 'No provider found for ${tokens.first}' | ||
: 'No provider found for ${tokens.first}: ' + tokens.join(' -> '); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters