Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 18ceb4d

Browse files
kasperlmhevery
authored andcommitted
feat(parser): Add support for named arguments.
Closes #762
1 parent d9ceeac commit 18ceb4d

File tree

17 files changed

+622
-159
lines changed

17 files changed

+622
-159
lines changed

bin/parser_generator_for_spec.dart

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,5 +443,58 @@ main(arguments) {
443443
'x."foo"',
444444
'{(:0}',
445445
'{1234:0}',
446+
447+
"sub1(1)",
448+
"sub1(3, b: 2)",
449+
"sub2()",
450+
"sub2(a: 3)",
451+
"sub2(a: 3, b: 2)",
452+
"sub2(b: 4)",
453+
454+
"o.sub1(1)",
455+
"o.sub1(3, b: 2)",
456+
"o.sub2()",
457+
"o.sub2(a: 3)",
458+
"o.sub2(a: 3, b: 2)",
459+
"o.sub2(b: 4)",
460+
461+
"(sub1)(1)",
462+
"(sub1)(3, b: 2)",
463+
"(sub2)()",
464+
"(sub2)(a: 3)",
465+
"(sub2)(a: 3, b: 2)",
466+
"(sub2)(b: 4)",
467+
468+
'foo(a: 0, a: 1)',
469+
'foo(a: 0, b: 1, a: 2)',
470+
'foo(0, a: 1, a: 2)',
471+
'foo(0, a: 1, b: 2, a: 3)',
472+
473+
'foo(if: 0)',
474+
'foo(a: 0, class: 0)',
475+
476+
'foo(a: 0)',
477+
'foo(a: 0, b: 1)',
478+
'foo(b: 1, a: 0)',
479+
'foo(0)',
480+
'foo(0, a: 0)',
481+
'foo(0, a: 0, b: 1)',
482+
'foo(0, b: 1, a: 0)',
483+
484+
'o.foo(a: 0)',
485+
'o.foo(a: 0, b: 1)',
486+
'o.foo(b: 1, a: 0)',
487+
'o.foo(0)',
488+
'o.foo(0, a: 0)',
489+
'o.foo(0, a: 0, b: 1)',
490+
'o.foo(0, b: 1, a: 0)',
491+
492+
'(foo)(a: 0)',
493+
'(foo)(a: 0, b: 1)',
494+
'(foo)(b: 1, a: 0)',
495+
'(foo)(0)',
496+
'(foo)(0, a: 0)',
497+
'(foo)(0, a: 0, b: 1)',
498+
'(foo)(0, b: 1, a: 0)',
446499
]);
447500
}

example/pubspec.lock

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ packages:
44
analyzer:
55
description: analyzer
66
source: hosted
7-
version: "0.11.10"
7+
version: "0.12.2"
88
angular:
99
description:
1010
path: ".."
@@ -15,30 +15,42 @@ packages:
1515
description: args
1616
source: hosted
1717
version: "0.9.0"
18+
barback:
19+
description: barback
20+
source: hosted
21+
version: "0.11.1"
1822
browser:
1923
description: browser
2024
source: hosted
2125
version: "0.9.1"
26+
code_transformers:
27+
description: code_transformers
28+
source: hosted
29+
version: "0.0.1-dev.2"
2230
collection:
2331
description: collection
2432
source: hosted
2533
version: "0.9.1"
2634
di:
2735
description: di
2836
source: hosted
29-
version: "0.0.33"
37+
version: "0.0.34"
3038
html5lib:
3139
description: html5lib
3240
source: hosted
3341
version: "0.9.2"
3442
intl:
3543
description: intl
3644
source: hosted
37-
version: "0.9.7"
45+
version: "0.8.10+4"
3846
logging:
3947
description: logging
4048
source: hosted
4149
version: "0.9.1+1"
50+
meta:
51+
description: meta
52+
source: hosted
53+
version: "0.8.8"
4254
path:
4355
description: path
4456
source: hosted

lib/change_detection/ast.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class PureFunctionAST extends AST {
8484
super('$name(${_argList(argsAST)})');
8585

8686
WatchRecord<_Handler> setupWatch(WatchGroup watchGroup) =>
87-
watchGroup.addFunctionWatch(fn, argsAST, expression);
87+
watchGroup.addFunctionWatch(fn, argsAST, const {}, expression);
8888
}
8989

9090
/**
@@ -96,15 +96,16 @@ class MethodAST extends AST {
9696
final AST lhsAST;
9797
final String name;
9898
final List<AST> argsAST;
99+
final Map<Symbol, AST> namedArgsAST;
99100

100-
MethodAST(lhsAST, name, argsAST)
101+
MethodAST(lhsAST, name, argsAST, [this.namedArgsAST = const {}])
101102
: lhsAST = lhsAST,
102103
name = name,
103104
argsAST = argsAST,
104105
super('$lhsAST.$name(${_argList(argsAST)})');
105106

106107
WatchRecord<_Handler> setupWatch(WatchGroup watchGroup) =>
107-
watchGroup.addMethodWatch(lhsAST, name, argsAST, expression);
108+
watchGroup.addMethodWatch(lhsAST, name, argsAST, namedArgsAST, expression);
108109
}
109110

110111

lib/change_detection/watch_group.dart

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,9 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
186186
* - [expression] normalized expression used for caching.
187187
*/
188188
_EvalWatchRecord addFunctionWatch(/* dartbug.com/16401 Function */ fn, List<AST> argsAST,
189+
Map<Symbol, AST> namedArgsAST,
189190
String expression) =>
190-
_addEvalWatch(null, fn, null, argsAST, expression);
191+
_addEvalWatch(null, fn, null, argsAST, namedArgsAST, expression);
191192

192193
/**
193194
* Watch a method [name]ed represented by an [expression].
@@ -198,13 +199,16 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
198199
* - [expression] normalized expression used for caching.
199200
*/
200201
_EvalWatchRecord addMethodWatch(AST lhs, String name, List<AST> argsAST,
202+
Map<Symbol, AST> namedArgsAST,
201203
String expression) =>
202-
_addEvalWatch(lhs, null, name, argsAST, expression);
204+
_addEvalWatch(lhs, null, name, argsAST, namedArgsAST, expression);
203205

204206

205207

206208
_EvalWatchRecord _addEvalWatch(AST lhsAST, /* dartbug.com/16401 Function */ fn, String name,
207-
List<AST> argsAST, String expression) {
209+
List<AST> argsAST,
210+
Map<Symbol, AST> namedArgsAST,
211+
String expression) {
208212
_InvokeHandler invokeHandler = new _InvokeHandler(this, expression);
209213
var evalWatchRecord = new _EvalWatchRecord(this, invokeHandler, fn, name,
210214
argsAST.length);
@@ -218,15 +222,24 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
218222
}
219223

220224
// Convert the args from AST to WatchRecords
221-
var i = 0;
222-
argsAST.map((ast) =>
223-
_cache.putIfAbsent(ast.expression, () => ast.setupWatch(this)))
224-
.forEach((WatchRecord<_Handler> record) {
225-
var argHandler = new _ArgHandler(this, evalWatchRecord, i++);
226-
_ArgHandlerList._add(invokeHandler, argHandler);
227-
record.handler.addForwardHandler(argHandler);
228-
argHandler.acceptValue(record.currentValue);
229-
});
225+
Iterable<WatchRecord<_Handler>> records = argsAST.map((ast) =>
226+
_cache.putIfAbsent(ast.expression, () => ast.setupWatch(this)));
227+
int i = 0;
228+
records.forEach((WatchRecord<_Handler> record) {
229+
_ArgHandler handler = new _PositionalArgHandler(this, evalWatchRecord, i++);
230+
_ArgHandlerList._add(invokeHandler, handler);
231+
record.handler.addForwardHandler(handler);
232+
handler.acceptValue(record.currentValue);
233+
});
234+
235+
namedArgsAST.forEach((Symbol name, AST ast) {
236+
WatchRecord<_Handler> record = _cache.putIfAbsent(ast.expression,
237+
() => ast.setupWatch(this));
238+
_ArgHandler handler = new _NamedArgHandler(this, evalWatchRecord, name);
239+
_ArgHandlerList._add(invokeHandler, handler);
240+
record.handler.addForwardHandler(handler);
241+
handler.acceptValue(record.currentValue);
242+
});
230243

231244
// Must be done last
232245
_EvalWatchList._add(this, evalWatchRecord);
@@ -615,25 +628,42 @@ class _CollectionHandler extends _Handler {
615628
}
616629
}
617630

618-
class _ArgHandler extends _Handler {
631+
abstract class _ArgHandler extends _Handler {
619632
_ArgHandler _previousArgHandler, _nextArgHandler;
620633

621634
// TODO(misko): Why do we override parent?
622635
final _EvalWatchRecord watchRecord;
623-
final int index;
636+
_ArgHandler(WatchGroup watchGrp, String expression, this.watchRecord)
637+
: super(watchGrp, expression);
624638

625639
_releaseWatch() => null;
640+
}
626641

627-
_ArgHandler(WatchGroup watchGrp, this.watchRecord, int index)
628-
: index = index,
629-
super(watchGrp, 'arg[$index]');
642+
class _PositionalArgHandler extends _ArgHandler {
643+
final int index;
644+
_PositionalArgHandler(WatchGroup watchGrp, _EvalWatchRecord record, int index)
645+
: this.index = index,
646+
super(watchGrp, 'arg[$index]', record);
630647

631648
void acceptValue(object) {
632649
watchRecord.dirtyArgs = true;
633650
watchRecord.args[index] = object;
634651
}
635652
}
636653

654+
class _NamedArgHandler extends _ArgHandler {
655+
final Symbol name;
656+
657+
_NamedArgHandler(WatchGroup watchGrp, _EvalWatchRecord record, Symbol name)
658+
: this.name = name,
659+
super(watchGrp, 'namedArg[$name]', record);
660+
661+
void acceptValue(object) {
662+
watchRecord.dirtyArgs = true;
663+
watchRecord.namedArgs[name] = object;
664+
}
665+
}
666+
637667
class _InvokeHandler extends _Handler implements _ArgHandlerList {
638668
_ArgHandler _argHandlerHead, _argHandlerTail;
639669

@@ -675,6 +705,7 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, Record<_Handler> {
675705
WatchGroup watchGrp;
676706
final _Handler handler;
677707
final List args;
708+
final Map<Symbol, dynamic> namedArgs = new Map<Symbol, dynamic>();
678709
final Symbol symbol;
679710
final String name;
680711
int mode;
@@ -751,7 +782,7 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, Record<_Handler> {
751782
return false;
752783
case _MODE_FUNCTION_:
753784
if (!dirtyArgs) return false;
754-
value = Function.apply(fn, args);
785+
value = Function.apply(fn, args, namedArgs);
755786
dirtyArgs = false;
756787
break;
757788
case _MODE_FUNCTION_APPLY_:
@@ -761,14 +792,14 @@ class _EvalWatchRecord implements WatchRecord<_Handler>, Record<_Handler> {
761792
break;
762793
case _MODE_FIELD_CLOSURE_:
763794
var closure = _instanceMirror.getField(symbol).reflectee;
764-
value = closure == null ? null : Function.apply(closure, args);
795+
value = closure == null ? null : Function.apply(closure, args, namedArgs);
765796
break;
766797
case _MODE_MAP_CLOSURE_:
767798
var closure = object[name];
768-
value = closure == null ? null : Function.apply(closure, args);
799+
value = closure == null ? null : Function.apply(closure, args, namedArgs);
769800
break;
770801
case _MODE_METHOD_:
771-
value = _instanceMirror.invoke(symbol, args).reflectee;
802+
value = _instanceMirror.invoke(symbol, args, namedArgs).reflectee;
772803
break;
773804
default:
774805
assert(false);

lib/core/parser/dynamic_parser.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import 'package:angular/core/parser/utils.dart' show EvalError;
1414
class ClosureMap {
1515
Getter lookupGetter(String name) => null;
1616
Setter lookupSetter(String name) => null;
17-
Function lookupFunction(String name, int arity) => null;
17+
Function lookupFunction(String name, CallArguments arguments) => null;
1818
}
1919

2020
@NgInjectableService()
@@ -128,33 +128,35 @@ class DynamicParserBackend extends ParserBackend {
128128

129129
Expression newCallScope(name, arguments) {
130130
Function constructor = _computeCallConstructor(
131-
_callScopeConstructors, name, arguments.length);
131+
_callScopeConstructors, name, arguments);
132132
return (constructor != null)
133133
? constructor(name, arguments, _closures)
134134
: new CallScope(name, arguments);
135135
}
136136

137137
Expression newCallMember(object, name, arguments) {
138138
Function constructor = _computeCallConstructor(
139-
_callMemberConstructors, name, arguments.length);
139+
_callMemberConstructors, name, arguments);
140140
return (constructor != null)
141141
? constructor(object, name, arguments, _closures)
142142
: new CallMember(object, name, arguments);
143143
}
144144

145-
Function _computeCallConstructor(Map constructors, String name, int arity) {
146-
Function function = _closures.lookupFunction(name, arity);
147-
return (function == null) ? null : constructors[arity];
145+
Function _computeCallConstructor(Map constructors,
146+
String name,
147+
CallArguments arguments) {
148+
Function function = _closures.lookupFunction(name, arguments);
149+
return (function == null) ? null : constructors[arguments.arity];
148150
}
149151

150152
static final Map<int, Function> _callScopeConstructors = {
151-
0: (n, a, c) => new CallScopeFast0(n, a, c.lookupFunction(n, 0)),
152-
1: (n, a, c) => new CallScopeFast1(n, a, c.lookupFunction(n, 1)),
153+
0: (n, a, c) => new CallScopeFast0(n, a, c.lookupFunction),
154+
1: (n, a, c) => new CallScopeFast1(n, a, c.lookupFunction),
153155
};
154156

155157
static final Map<int, Function> _callMemberConstructors = {
156-
0: (o, n, a, c) => new CallMemberFast0(o, n, a, c.lookupFunction(n, 0)),
157-
1: (o, n, a, c) => new CallMemberFast1(o, n, a, c.lookupFunction(n, 1)),
158+
0: (o, n, a, c) => new CallMemberFast0(o, n, a, c.lookupFunction),
159+
1: (o, n, a, c) => new CallMemberFast1(o, n, a, c.lookupFunction),
158160
};
159161
}
160162

0 commit comments

Comments
 (0)