@@ -34,7 +34,7 @@ class Mock {
34
34
35
35
dynamic noSuchMethod (Invocation invocation) {
36
36
if (_typedArgs.isNotEmpty || _typedNamedArgs.isNotEmpty) {
37
- invocation = _reconstituteInvocation (invocation);
37
+ invocation = new _InvocationForTypedArguments (invocation);
38
38
}
39
39
if (_whenInProgress) {
40
40
_whenCall = new _WhenCall (this , invocation);
@@ -60,26 +60,20 @@ class Mock {
60
60
String toString () => _givenName != null ? _givenName : runtimeType.toString ();
61
61
}
62
62
63
- // Return a new [Invocation], reconstituted from [invocation], [_typedArgs],
64
- // and [_typedNamedArgs].
65
- Invocation _reconstituteInvocation (Invocation invocation) {
66
- var newInvocation = new FakeInvocation (invocation);
67
- return newInvocation;
68
- }
69
-
70
- /// An Invocation implementation that allows all attributes to be passed into
71
- /// the constructor.
72
- class FakeInvocation extends Invocation {
63
+ /// An Invocation implementation that takes arguments from [_typedArgs] and
64
+ /// [_typedNamedArgs] .
65
+ class _InvocationForTypedArguments extends Invocation {
73
66
final Symbol memberName;
74
67
final Map <Symbol , dynamic > namedArguments;
75
68
final List <dynamic > positionalArguments;
76
69
final bool isGetter;
77
70
final bool isMethod;
78
71
final bool isSetter;
79
72
80
- factory FakeInvocation (Invocation invocation) {
73
+ factory _InvocationForTypedArguments (Invocation invocation) {
81
74
if (_typedArgs.isEmpty && _typedNamedArgs.isEmpty) {
82
- throw new StateError ("FakeInvocation called when no typed calls have been saved." );
75
+ throw new StateError (
76
+ "_InvocationForTypedArguments called when no typed calls have been saved." );
83
77
}
84
78
85
79
// Handle named arguments first, so that we can provide useful errors for
@@ -92,7 +86,7 @@ class FakeInvocation extends Invocation {
92
86
_typedArgs.clear ();
93
87
_typedNamedArgs.clear ();
94
88
95
- return new FakeInvocation ._(
89
+ return new _InvocationForTypedArguments ._(
96
90
invocation.memberName,
97
91
positionalArguments,
98
92
namedArguments,
@@ -101,42 +95,52 @@ class FakeInvocation extends Invocation {
101
95
invocation.isSetter);
102
96
}
103
97
98
+ // Reconstitutes the named arguments in an invocation from [_typedNamedArgs].
99
+ //
100
+ // The namedArguments in [invocation] which are null should be represented
101
+ // by a stored value in [_typedNamedArgs]. The null presumably came from
102
+ // [typed].
104
103
static Map <Symbol ,dynamic > _reconstituteNamedArgs (Invocation invocation) {
105
104
var namedArguments = < Symbol , dynamic > {};
106
105
var _typedNamedArgSymbols = _typedNamedArgs.keys.map ((name) => new Symbol (name));
106
+
107
+ // Iterate through [invocation]'s named args, validate them, and add them
108
+ // to the return map.
107
109
invocation.namedArguments.forEach ((name, arg) {
108
110
if (arg == null ) {
109
111
if (! _typedNamedArgSymbols.contains (name)) {
110
112
// Incorrect usage of [typed], something like:
111
113
// `when(obj.fn(a: typed(any)))`.
112
114
throw new ArgumentError (
113
115
'A typed argument was passed in as a named argument named "$name ", '
114
- 'but did not a value for its name . Each typed argument that is '
115
- 'passed as a named argument needs to specify the `name ` argument. '
116
- 'For example: `when(obj.fn(x: typed(any, name : "x")))`.' );
116
+ 'but did not pass a value for `named` . Each typed argument that is '
117
+ 'passed as a named argument needs to specify the `named ` argument. '
118
+ 'For example: `when(obj.fn(x: typed(any, named : "x")))`.' );
117
119
}
118
120
} else {
119
121
// Add each real named argument that was _not_ passed with [typed].
120
122
namedArguments[name] = arg;
121
123
}
122
124
});
123
125
126
+ // Iterate through the stored named args (stored with [typed]), validate
127
+ // them, and add them to the return map.
124
128
_typedNamedArgs.forEach ((name, arg) {
125
129
Symbol nameSymbol = new Symbol (name);
126
130
if (! invocation.namedArguments.containsKey (nameSymbol)) {
127
- // Incorrect usage of [name], something like:
128
- // `when(obj.fn(typed(any, name: 'a')))`.
129
131
throw new ArgumentError (
130
- 'A typed argument was declared with name $name , but was not passed '
131
- 'as an argument named $name .' );
132
+ 'A typed argument was declared as named $name , but was not passed '
133
+ 'as an argument named $name .\n\n '
134
+ 'BAD: when(obj.fn(typed(any, named: "a")))\n '
135
+ 'GOOD: when(obj.fn(a: typed(any, named: "a")))' );
132
136
}
133
137
if (invocation.namedArguments[nameSymbol] != null ) {
134
- // Incorrect usage of [name], something like:
135
- // `when(obj.fn(a: typed(any, name: 'b'), b: "string"))`.
136
138
throw new ArgumentError (
137
- 'A typed argument was declared with name $name , but a different '
139
+ 'A typed argument was declared as named $name , but a different '
138
140
'value (${invocation .namedArguments [nameSymbol ]}) was passed as '
139
- '$name .' );
141
+ '$name .\n\n '
142
+ 'BAD: when(obj.fn(b: typed(any, name: "a")))\n '
143
+ 'GOOD: when(obj.fn(b: typed(any, name: "b")))' );
140
144
}
141
145
namedArguments[nameSymbol] = arg;
142
146
});
@@ -153,31 +157,32 @@ class FakeInvocation extends Invocation {
153
157
'null arguments are not allowed alongside typed(); use '
154
158
'"typed(eq(null))"' );
155
159
}
156
- int i = 0 ;
157
- int j = 0 ;
158
- while (i < _typedArgs.length && j < invocation.positionalArguments.length) {
159
- var arg = _typedArgs[i];
160
- if (invocation.positionalArguments[j] == null ) {
160
+ int typedIndex = 0 ;
161
+ int positionalIndex = 0 ;
162
+ while (typedIndex < _typedArgs.length &&
163
+ positionalIndex < invocation.positionalArguments.length) {
164
+ var arg = _typedArgs[typedIndex];
165
+ if (invocation.positionalArguments[positionalIndex] == null ) {
161
166
// [typed] was used; add the [_ArgMatcher] given to [typed].
162
167
positionalArguments.add (arg);
163
- i ++ ;
164
- j ++ ;
168
+ typedIndex ++ ;
169
+ positionalIndex ++ ;
165
170
} else {
166
171
// [typed] was not used; add the [_ArgMatcher] from [invocation].
167
- positionalArguments.add (invocation.positionalArguments[j ]);
168
- j ++ ;
172
+ positionalArguments.add (invocation.positionalArguments[positionalIndex ]);
173
+ positionalIndex ++ ;
169
174
}
170
175
}
171
- while (j < invocation.positionalArguments.length) {
176
+ while (positionalIndex < invocation.positionalArguments.length) {
172
177
// Some trailing non-[typed] arguments.
173
- positionalArguments.add (invocation.positionalArguments[j ]);
174
- j ++ ;
178
+ positionalArguments.add (invocation.positionalArguments[positionalIndex ]);
179
+ positionalIndex ++ ;
175
180
}
176
181
177
182
return positionalArguments;
178
183
}
179
184
180
- FakeInvocation ._(
185
+ _InvocationForTypedArguments ._(
181
186
this .memberName,
182
187
this .positionalArguments,
183
188
this .namedArguments,
@@ -431,11 +436,11 @@ get captureAny => new _ArgMatcher(anything, true);
431
436
captureThat (Matcher matcher) => new _ArgMatcher (matcher, true );
432
437
argThat (Matcher matcher) => new _ArgMatcher (matcher, false );
433
438
434
- /*=T*/ typed/*<T>*/ (_ArgMatcher matcher, {String name }) {
435
- if (name == null ) {
439
+ /*=T*/ typed/*<T>*/ (_ArgMatcher matcher, {String named }) {
440
+ if (named == null ) {
436
441
_typedArgs.add (matcher);
437
442
} else {
438
- _typedNamedArgs[name ] = matcher;
443
+ _typedNamedArgs[named ] = matcher;
439
444
}
440
445
return null ;
441
446
}
0 commit comments