Skip to content

Commit d320b5e

Browse files
authored
Mustachio: Implement Property.isNullValue, renderValue; section rendering; lots of tests (#2448)
1 parent 067c661 commit d320b5e

File tree

8 files changed

+800
-268
lines changed

8 files changed

+800
-268
lines changed

lib/src/generator/templates.renderers.dart

Lines changed: 538 additions & 256 deletions
Large diffs are not rendered by default.

lib/src/mustachio/parser.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class MustachioParser {
8282
addTextNode(textStartIndex, textEndIndex);
8383
children.add(result.node);
8484
textStartIndex = _index;
85+
continue;
8586
}
8687
}
8788
_index++;

lib/src/mustachio/renderer_base.dart

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,44 @@ abstract class RendererBase<T> {
7575
}
7676

7777
void section(Section node) {
78-
// TODO(srawlins): Implement.
78+
var key = node.key.first;
79+
var property = getProperty(key);
80+
if (property == null) {
81+
if (parent == null) {
82+
throw MustachioResolutionError(
83+
'Failed to resolve $key as a property on any types in the current '
84+
'context');
85+
} else {
86+
return parent.section(node);
87+
}
88+
}
89+
90+
if (property.getBool != null) {
91+
var boolResult = property.getBool(context);
92+
if ((boolResult && !node.invert) || (!boolResult && node.invert)) {
93+
renderBlock(node.children);
94+
}
95+
return;
96+
}
97+
98+
if (property.renderIterable != null) {
99+
// An inverted section is rendered with the current context.
100+
if (node.invert && property.isEmptyIterable(context)) {
101+
renderBlock(node.children);
102+
}
103+
if (!node.invert && !property.isEmptyIterable(context)) {
104+
write(property.renderIterable(context, this, node.children));
105+
}
106+
return;
107+
}
108+
109+
// If this section is not a conditional or repeated section, it is a value
110+
// section, regardless of type.
111+
if (node.invert && property.isNullValue(context)) {
112+
renderBlock(node.children);
113+
} else if (!node.invert && !property.isNullValue(context)) {
114+
write(property.renderValue(context, this, node.children));
115+
}
79116
}
80117

81118
void partial(Partial node) {
@@ -103,14 +140,21 @@ class Property<T> {
103140
T, RendererBase<T>, List<MustachioNode> /*!*/) /*?*/
104141
renderIterable;
105142

143+
final bool /*!*/ Function(T) /*?*/ isNullValue;
144+
145+
final String /*!*/ Function(
146+
T, RendererBase<T>, List<MustachioNode> /*!*/) /*?*/ renderValue;
147+
106148
// TODO(srawlins): Add functions for rendering other properties.
107149

108150
Property(
109151
{@required this.getValue,
110152
this.getProperties,
111153
this.getBool,
112154
this.isEmptyIterable,
113-
this.renderIterable});
155+
this.renderIterable,
156+
this.isNullValue,
157+
this.renderValue});
114158
}
115159

116160
/// An error indicating that a renderer failed to resolve a key.

test/mustachio/builder_test.dart

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,6 @@ class Bar {}
126126
'static Map<String, Property<CT_>> propertyMap<CT_ extends Foo>() => {'));
127127
});
128128

129-
test('with a property map with a String property', () {
130-
expect(generatedContent, contains('''
131-
's1': Property(
132-
getValue: (CT_ c) => c.s1,
133-
getProperties: _Renderer_String.propertyMap,
134-
),
135-
'''));
136-
});
137-
138129
test('with a property map which references the superclass', () {
139130
expect(generatedContent,
140131
contains('..._Renderer_FooBase.propertyMap<CT_>(),'));
@@ -165,6 +156,19 @@ class Bar {}
165156
return buffer.toString();
166157
},
167158
),
159+
'''));
160+
});
161+
162+
test('with a property map with a non-bool, non-Iterable property', () {
163+
expect(generatedContent, contains('''
164+
's1': Property(
165+
getValue: (CT_ c) => c.s1,
166+
getProperties: _Renderer_String.propertyMap,
167+
isNullValue: (CT_ c) => c.s1 == null,
168+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
169+
return _render_String(c.s1, ast, parent: r);
170+
},
171+
),
168172
'''));
169173
});
170174
});

test/mustachio/foo.renderers.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class Renderer_Foo extends RendererBase<Foo> {
4040
's1': Property(
4141
getValue: (CT_ c) => c.s1,
4242
getProperties: Renderer_String.propertyMap,
43+
isNullValue: (CT_ c) => c.s1 == null,
44+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
45+
return _render_String(c.s1, ast, parent: r);
46+
},
4347
),
4448
...Renderer_Object.propertyMap<CT_>(),
4549
};
@@ -82,6 +86,10 @@ class Renderer_String extends RendererBase<String> {
8286
'hashCode': Property(
8387
getValue: (CT_ c) => c.hashCode,
8488
getProperties: Renderer_int.propertyMap,
89+
isNullValue: (CT_ c) => c.hashCode == null,
90+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
91+
return _render_int(c.hashCode, ast, parent: r);
92+
},
8593
),
8694
'isEmpty': Property(
8795
getValue: (CT_ c) => c.isEmpty,
@@ -96,6 +104,10 @@ class Renderer_String extends RendererBase<String> {
96104
'length': Property(
97105
getValue: (CT_ c) => c.length,
98106
getProperties: Renderer_int.propertyMap,
107+
isNullValue: (CT_ c) => c.length == null,
108+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
109+
return _render_int(c.length, ast, parent: r);
110+
},
99111
),
100112
'runes': Property(
101113
getValue: (CT_ c) => c.runes,
@@ -137,6 +149,10 @@ class Renderer_Object extends RendererBase<Object> {
137149
'hashCode': Property(
138150
getValue: (CT_ c) => c.hashCode,
139151
getProperties: Renderer_int.propertyMap,
152+
isNullValue: (CT_ c) => c.hashCode == null,
153+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
154+
return _render_int(c.hashCode, ast, parent: r);
155+
},
140156
),
141157
};
142158

@@ -165,6 +181,10 @@ class Renderer_bool extends RendererBase<bool> {
165181
'hashCode': Property(
166182
getValue: (CT_ c) => c.hashCode,
167183
getProperties: Renderer_int.propertyMap,
184+
isNullValue: (CT_ c) => c.hashCode == null,
185+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
186+
return _render_int(c.hashCode, ast, parent: r);
187+
},
168188
),
169189
...Renderer_Object.propertyMap<CT_>(),
170190
};
@@ -194,6 +214,10 @@ class Renderer_List<E> extends RendererBase<List<E>> {
194214
'length': Property(
195215
getValue: (CT_ c) => c.length,
196216
getProperties: Renderer_int.propertyMap,
217+
isNullValue: (CT_ c) => c.length == null,
218+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
219+
return _render_int(c.length, ast, parent: r);
220+
},
197221
),
198222
'reversed': Property(
199223
getValue: (CT_ c) => c.reversed,
@@ -226,6 +250,10 @@ class Renderer_int extends RendererBase<int> {
226250
'bitLength': Property(
227251
getValue: (CT_ c) => c.bitLength,
228252
getProperties: Renderer_int.propertyMap,
253+
isNullValue: (CT_ c) => c.bitLength == null,
254+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
255+
return _render_int(c.bitLength, ast, parent: r);
256+
},
229257
),
230258
'isEven': Property(
231259
getValue: (CT_ c) => c.isEven,
@@ -240,6 +268,10 @@ class Renderer_int extends RendererBase<int> {
240268
'sign': Property(
241269
getValue: (CT_ c) => c.sign,
242270
getProperties: Renderer_int.propertyMap,
271+
isNullValue: (CT_ c) => c.sign == null,
272+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
273+
return _render_int(c.sign, ast, parent: r);
274+
},
243275
),
244276
...Renderer_num.propertyMap<CT_>(),
245277
};
@@ -269,6 +301,10 @@ class Renderer_num extends RendererBase<num> {
269301
'hashCode': Property(
270302
getValue: (CT_ c) => c.hashCode,
271303
getProperties: Renderer_int.propertyMap,
304+
isNullValue: (CT_ c) => c.hashCode == null,
305+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
306+
return _render_int(c.hashCode, ast, parent: r);
307+
},
272308
),
273309
'isFinite': Property(
274310
getValue: (CT_ c) => c.isFinite,
@@ -293,6 +329,10 @@ class Renderer_num extends RendererBase<num> {
293329
'sign': Property(
294330
getValue: (CT_ c) => c.sign,
295331
getProperties: Renderer_num.propertyMap,
332+
isNullValue: (CT_ c) => c.sign == null,
333+
renderValue: (CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
334+
return _render_num(c.sign, ast, parent: r);
335+
},
296336
),
297337
...Renderer_Object.propertyMap<CT_>(),
298338
};

test/mustachio/parser_test.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,17 @@ void main() {
216216
expect(section.children, isEmpty);
217217
});
218218

219+
test('parses section with variable tag inside', () {
220+
var parser = MustachioParser('Text {{#key}}{{two}}{{/key}}');
221+
var ast = parser.parse();
222+
expect(ast, hasLength(2));
223+
_expectText(ast[0], equals('Text '));
224+
var section = ast[1] as Section;
225+
_expectSection(section, equals(['key']));
226+
expect(section.children, hasLength(1));
227+
_expectVariable(section.children.single, equals(['two']));
228+
});
229+
219230
test('parses section with empty key as text', () {
220231
var parser = MustachioParser('Text {{#}}{{/key}}');
221232
var ast = parser.parse();

0 commit comments

Comments
 (0)