@@ -180,29 +180,24 @@ abstract class RendererBase<T> {
180
180
return context.toString ();
181
181
}
182
182
var firstName = names.first;
183
- var property = getProperty (firstName);
184
- if (property != null ) {
185
- var remainingNames = [...names.skip (1 )];
186
- try {
187
- return property.renderVariable (context, property, remainingNames);
188
- } on PartialMustachioResolutionError catch (e) {
189
- // The error thrown by [Property.renderVariable] does not have all of
190
- // the names required for a decent error. We throw a new error here.
191
- throw MustachioResolutionError (node.keySpan.message (
192
- "Failed to resolve '${e .name }' on ${e .contextType } while resolving "
193
- '$remainingNames as a property chain on any types in the context '
194
- "chain: $contextChainString , after first resolving '$firstName ' to "
195
- 'a property on $T ' ));
183
+ try {
184
+ var property = getProperty (firstName);
185
+ if (property != null ) {
186
+ var remainingNames = [...names.skip (1 )];
187
+ try {
188
+ return property.renderVariable (context, property, remainingNames);
189
+ } on PartialMustachioResolutionError catch (e) {
190
+ // The error thrown by [Property.renderVariable] does not have all of
191
+ // the names required for a decent error. We throw a new error here.
192
+ throw MustachioResolutionError (node.keySpan.message (
193
+ "Failed to resolve '${e .name }' on ${e .contextType } while "
194
+ 'resolving $remainingNames as a property chain on any types in '
195
+ 'the context chain: $contextChainString , after first resolving '
196
+ "'$firstName ' to a property on $T " ));
197
+ }
196
198
}
197
- }
198
-
199
- if (this is SimpleRenderer && _invisibleGetters.contains (names.first)) {
200
- var type = context.runtimeType;
201
- throw MustachioResolutionError (node.keySpan.message (
202
- '$firstName is a getter on $type , which is not visible to Mustache. '
203
- 'To render $firstName on $type , make it visible to mustache; to '
204
- 'render $firstName on a different type up in the context stack, '
205
- 'perhaps provide $firstName via a different name.' ));
199
+ } on _MustachioResolutionErrorWithoutSpan catch (e) {
200
+ throw MustachioResolutionError (node.keySpan.message (e.message));
206
201
}
207
202
208
203
if (parent != null ) {
@@ -302,20 +297,37 @@ class SimpleRenderer extends RendererBase<Object> {
302
297
) : super (context, parent, template, invisibleGetters: invisibleGetters);
303
298
304
299
@override
305
- Property <Object > getProperty (String key) => null ;
300
+ Property <Object > getProperty (String key) {
301
+ if (_invisibleGetters.contains (key)) {
302
+ throw MustachioResolutionError (_failedKeyVisibilityMessage (key));
303
+ } else {
304
+ return null ;
305
+ }
306
+ }
306
307
307
308
@override
308
309
String getFields (Variable node) {
309
310
var names = node.key;
310
- if (names.length == 1 && names.single == '.' ) {
311
+ var firstName = node.key.first;
312
+ if (names.length == 1 && firstName == '.' ) {
311
313
return context.toString ();
312
- }
313
- if (parent != null ) {
314
+ } else if (_invisibleGetters.contains (firstName)) {
315
+ throw MustachioResolutionError (_failedKeyVisibilityMessage (firstName));
316
+ } else if (parent != null ) {
314
317
return parent.getFields (node);
315
318
} else {
316
319
return 'null' ;
317
320
}
318
321
}
322
+
323
+ String _failedKeyVisibilityMessage (String name) {
324
+ var type = context.runtimeType;
325
+ return '[$name ] is a getter on $type , which is not visible to Mustache. '
326
+ 'To render [$name ] on $type , make it visible to Mustache via the '
327
+ '`visibleTypes` parameter on `@Renderer`; to render [$name ] on a '
328
+ 'different type up in the context stack, perhaps provide [$name ] via '
329
+ 'a different name.' ;
330
+ }
319
331
}
320
332
321
333
/// An individual property of objects of type [T] , including functions for
@@ -369,7 +381,7 @@ class Property<T> {
369
381
class MustachioResolutionError extends Error {
370
382
final String message;
371
383
372
- MustachioResolutionError ([ this .message] );
384
+ MustachioResolutionError (this .message);
373
385
374
386
@override
375
387
String toString () => 'MustachioResolutionError: $message ' ;
@@ -385,6 +397,17 @@ class PartialMustachioResolutionError extends Error {
385
397
PartialMustachioResolutionError (this .name, this .contextType);
386
398
}
387
399
400
+ /// A Mustachio resolution error which is thrown in a position where the AST
401
+ /// node is not known.
402
+ ///
403
+ /// This error should be caught and "re-thrown" as a [MustachioResolutionError]
404
+ /// with a message derived from a [SourceSpan] .
405
+ class _MustachioResolutionErrorWithoutSpan extends Error {
406
+ final String message;
407
+
408
+ _MustachioResolutionErrorWithoutSpan (this .message);
409
+ }
410
+
388
411
extension MapExtensions <T > on Map <String , Property <T >> {
389
412
Property <T > getValue (String name) {
390
413
if (containsKey (name)) {
0 commit comments