Skip to content

Commit 5df03dd

Browse files
authored
Convert various Mustachio errors to be exceptions. (dart-lang#3897)
I think I just got this wrong when I first implemented these; each of these is non-fatal, and expected to be caught later, so they should all be exceptions. This was all caught by the `avoid_catching_errors` lint rule.
1 parent b0328fd commit 5df03dd

File tree

4 files changed

+48
-45
lines changed

4 files changed

+48
-45
lines changed

lib/src/mustachio/renderer_base.dart

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
// See the Mustachio README at tool/mustachio/README.md for high-level
66
// documentation.
77

8+
/// @docImport 'package:source_span/source_span.dart';
9+
library;
10+
811
import 'dart:collection';
912
import 'dart:convert' show htmlEscape;
1013

1114
import 'package:analyzer/file_system/file_system.dart';
1215
import 'package:meta/meta.dart';
16+
1317
import 'parser.dart';
1418

1519
// TODO(devoncarew): See is we can make this synchronous.
@@ -119,7 +123,7 @@ class Template {
119123
partialTemplates: {...partialTemplates});
120124
partialTemplates[partialFile] = partialTemplate;
121125
} on FileSystemException catch (e) {
122-
throw MustachioResolutionError(span.message(
126+
throw MustachioResolutionException(span.message(
123127
'FileSystemException (${e.message}) when reading partial:'));
124128
}
125129
}
@@ -188,27 +192,26 @@ abstract class RendererBase<T extends Object?> {
188192
if (property != null) {
189193
try {
190194
return property.renderVariable(context, property, remainingNames);
191-
// ignore: avoid_catching_errors
192-
} on PartialMustachioResolutionError catch (e) {
193-
// The error thrown by [Property.renderVariable] does not have all of
194-
// the names required for a decent error. We throw a new error here.
195-
throw MustachioResolutionError(node.keySpan.message(
195+
} on PartialMustachioResolutionException catch (e) {
196+
// The exception thrown by [Property.renderVariable] does not have all
197+
// of the names required for a decent error. We throw a new error
198+
// here.
199+
throw MustachioResolutionException(node.keySpan.message(
196200
"Failed to resolve '${e.name}' on ${e.contextType} while "
197201
'resolving $remainingNames as a property chain on any types in '
198202
'the context chain: $contextChainString, after first resolving '
199203
"'$firstName' to a property on $T"));
200204
}
201205
}
202-
// ignore: avoid_catching_errors
203-
} on _MustachioResolutionErrorWithoutSpan catch (e) {
204-
throw MustachioResolutionError(node.keySpan.message(e.message));
206+
} on _MustachioResolutionExceptionWithoutSpan catch (e) {
207+
throw MustachioResolutionException(node.keySpan.message(e.message));
205208
}
206209

207210
final parent = this.parent;
208211
if (parent != null) {
209212
return parent.getFields(node);
210213
} else {
211-
throw MustachioResolutionError(node.keySpan.message(
214+
throw MustachioResolutionException(node.keySpan.message(
212215
"Failed to resolve '${names.first}' as a property on any types in "
213216
'the context chain: $contextChainString'));
214217
}
@@ -241,7 +244,7 @@ abstract class RendererBase<T extends Object?> {
241244
if (property == null) {
242245
final parent = this.parent;
243246
if (parent == null) {
244-
throw MustachioResolutionError(node.keySpan.message(
247+
throw MustachioResolutionException(node.keySpan.message(
245248
"Failed to resolve '$key' as a property on any types in the "
246249
'current context'));
247250
} else {
@@ -312,7 +315,7 @@ class SimpleRenderer extends RendererBase<Object?> {
312315
@override
313316
Property<Object>? getProperty(String key) {
314317
if (_invisibleGetters.contains(key)) {
315-
throw MustachioResolutionError(_failedKeyVisibilityMessage(key));
318+
throw MustachioResolutionException(_failedKeyVisibilityMessage(key));
316319
} else {
317320
return null;
318321
}
@@ -325,7 +328,8 @@ class SimpleRenderer extends RendererBase<Object?> {
325328
if (names.length == 1 && firstName == '.') {
326329
return context.toString();
327330
} else if (_invisibleGetters.contains(firstName)) {
328-
throw MustachioResolutionError(_failedKeyVisibilityMessage(firstName));
331+
throw MustachioResolutionException(
332+
_failedKeyVisibilityMessage(firstName));
329333
} else if (parent != null) {
330334
return parent!.getFields(node);
331335
} else {
@@ -380,7 +384,7 @@ class Property<T extends Object?> {
380384
if (remainingNames.isEmpty) {
381385
return getValue(c).toString();
382386
} else {
383-
throw MustachioResolutionError(
387+
throw MustachioResolutionException(
384388
_simpleResolveErrorMessage(remainingNames, typeString));
385389
}
386390
}
@@ -391,43 +395,43 @@ class Property<T extends Object?> {
391395
"annotation's 'visibleTypes' list";
392396
}
393397

394-
/// An error indicating that a renderer failed to resolve a key.
395-
class MustachioResolutionError extends Error {
398+
/// An exception indicating that a renderer failed to resolve a key.
399+
class MustachioResolutionException implements Exception {
396400
final String message;
397401

398-
MustachioResolutionError(this.message);
402+
MustachioResolutionException(this.message);
399403

400404
@override
401-
String toString() => 'MustachioResolutionError: $message';
405+
String toString() => 'MustachioResolutionException: $message';
402406
}
403407

404-
/// An error indicating that a renderer failed to resolve a follow-on name in a
405-
/// multi-name key.
406-
class PartialMustachioResolutionError extends Error {
408+
/// An exception indicating that a renderer failed to resolve a follow-on name
409+
/// in a multi-name key.
410+
class PartialMustachioResolutionException implements Exception {
407411
final String name;
408412

409413
final Type contextType;
410414

411-
PartialMustachioResolutionError(this.name, this.contextType);
415+
PartialMustachioResolutionException(this.name, this.contextType);
412416
}
413417

414-
/// A Mustachio resolution error which is thrown in a position where the AST
415-
/// node is not known.
418+
/// A Mustachio resolution exception which is thrown in a position where the
419+
/// AST node is not known.
416420
///
417-
/// This error should be caught and "re-thrown" as a [MustachioResolutionError]
418-
/// with a message derived from a [SourceSpan].
419-
class _MustachioResolutionErrorWithoutSpan extends Error {
421+
/// This exception should be caught and "re-thrown" as a
422+
/// [MustachioResolutionException] with a message derived from a [SourceSpan].
423+
class _MustachioResolutionExceptionWithoutSpan implements Exception {
420424
final String message;
421425

422-
_MustachioResolutionErrorWithoutSpan(this.message);
426+
_MustachioResolutionExceptionWithoutSpan(this.message);
423427
}
424428

425429
extension MapExtensions<T> on Map<String, Property<T>> {
426430
Property<T> getValue(String name) {
427431
if (containsKey(name)) {
428432
return this[name]!;
429433
} else {
430-
throw PartialMustachioResolutionError(name, T);
434+
throw PartialMustachioResolutionException(name, T);
431435
}
432436
}
433437
}

test/mustachio/aot_compiler_render_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ void main() {
554554
],
555555
'Foo()',
556556
),
557-
throwsA(const TypeMatcher<MustachioResolutionError>()
557+
throwsA(const TypeMatcher<MustachioResolutionException>()
558558
.having((e) => e.message, 'message', contains('''
559559
line 1, column 8 of lib/templates/foo.html: Failed to resolve '[s2]' as a property on any types in the context chain: [Foo]
560560
@@ -573,7 +573,7 @@ line 1, column 8 of lib/templates/foo.html: Failed to resolve '[s2]' as a proper
573573
],
574574
'Foo()',
575575
),
576-
throwsA(const TypeMatcher<MustachioResolutionError>()
576+
throwsA(const TypeMatcher<MustachioResolutionException>()
577577
.having((e) => e.message, 'message', contains('''
578578
line 1, column 9 of lib/templates/foo.html: Failed to resolve '[s2]' as a property on any types in the context chain: [Foo]
579579
@@ -592,7 +592,7 @@ line 1, column 9 of lib/templates/foo.html: Failed to resolve '[s2]' as a proper
592592
],
593593
'Bar()..foo = Foo()',
594594
),
595-
throwsA(const TypeMatcher<MustachioResolutionError>()
595+
throwsA(const TypeMatcher<MustachioResolutionException>()
596596
.having((e) => e.message, 'message', contains('''
597597
line 1, column 8 of lib/templates/bar.html: Failed to resolve 'x' on Bar while resolving [x] as a property chain on any types in the context chain: context0.foo, after first resolving 'foo' to a property on Foo?
598598
@@ -612,7 +612,7 @@ line 1, column 8 of lib/templates/bar.html: Failed to resolve 'x' on Bar while r
612612
],
613613
'Bar()..foo = Foo()',
614614
),
615-
throwsA(const TypeMatcher<MustachioResolutionError>()
615+
throwsA(const TypeMatcher<MustachioResolutionException>()
616616
.having((e) => e.message, 'message', contains('''
617617
line 1, column 13 of lib/templates/bar.html: Failed to resolve '[x]' as a property on any types in the context chain: [Foo, Bar]
618618

test/mustachio/runtime_renderer_render_test.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ World
478478
var foo = Foo();
479479
expect(
480480
() => renderFoo(foo, fooTemplate),
481-
throwsA(const TypeMatcher<MustachioResolutionError>()
481+
throwsA(const TypeMatcher<MustachioResolutionException>()
482482
.having((e) => e.message, 'message', contains('''
483483
line 1, column 8 of ${fooTemplateFile.path}: Failed to resolve 's2' as a property on any types in the context chain: Foo
484484
@@ -494,7 +494,7 @@ line 1, column 8 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
494494
var foo = Foo();
495495
expect(
496496
() => renderFoo(foo, fooTemplate),
497-
throwsA(const TypeMatcher<MustachioResolutionError>()
497+
throwsA(const TypeMatcher<MustachioResolutionException>()
498498
.having((e) => e.message, 'message', contains('''
499499
line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a property on any types in the current context
500500
@@ -511,7 +511,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
511511
var bar = Bar()..foo = Foo();
512512
expect(
513513
() => renderBar(bar, barTemplate),
514-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
514+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
515515
(e) => e.message,
516516
'message',
517517
contains("Failed to resolve 'x' on Foo while resolving [x] as a "
@@ -527,7 +527,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
527527
var bar = Bar()..foo = Foo();
528528
expect(
529529
() => renderBar(bar, barTemplate),
530-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
530+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
531531
(e) => e.message,
532532
'message',
533533
contains("Failed to resolve 'x' as a property on any types in the "
@@ -542,7 +542,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
542542
var foo = Foo();
543543
expect(
544544
() => renderFoo(foo, fooTemplate),
545-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
545+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
546546
(e) => e.message,
547547
'message',
548548
contains('Failed to resolve [length] property chain on String'))));
@@ -556,7 +556,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
556556
var foo = Foo()..s1 = 'String';
557557
expect(
558558
() => renderFoo(foo, fooTemplate),
559-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
559+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
560560
(e) => e.message,
561561
'message',
562562
contains('[length] is a getter on String, which is not visible to '
@@ -571,7 +571,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
571571
var foo = Foo()..s1 = 'String';
572572
expect(
573573
() => renderFoo(foo, fooTemplate),
574-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
574+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
575575
(e) => e.message,
576576
'message',
577577
contains('[length] is a getter on String, which is not visible to '
@@ -591,7 +591,7 @@ line 1, column 9 of ${fooTemplateFile.path}: Failed to resolve 's2' as a propert
591591
..writeAsStringSync('Text {{#foo}}{{>missing.mustache}}{{/foo}}');
592592
expect(
593593
() async => await Template.parse(barTemplateFile),
594-
throwsA(const TypeMatcher<MustachioResolutionError>().having(
594+
throwsA(const TypeMatcher<MustachioResolutionException>().having(
595595
(e) => e.message,
596596
'message',
597597
allOf(

tool/mustachio/codegen_aot_compiler.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ Future<Map<_AotCompiler, String>> _deduplicateRenderers(
158158
String compiledLubRenderer;
159159
try {
160160
compiledLubRenderer = await lubCompiler._compileToRenderer(referenceUris);
161-
// ignore: avoid_catching_errors
162-
} on MustachioResolutionError {
161+
} on MustachioResolutionException {
163162
// Oops, switching to the LUB type prevents the renderer from compiling;
164163
// likely the properties accessed in the partial are not all declared on
165164
// the LUB type.
@@ -624,7 +623,7 @@ class _BlockCompiler {
624623
}
625624
if (getter == null) {
626625
var contextTypes = [for (var c in _contextStack) c.type];
627-
throw MustachioResolutionError(node.keySpan
626+
throw MustachioResolutionException(node.keySpan
628627
.message("Failed to resolve '$key' as a property on any types in the "
629628
'context chain: $contextTypes'));
630629
}
@@ -642,7 +641,7 @@ class _BlockCompiler {
642641
for (var secondaryKey in remainingNames) {
643642
getter = type.lookUpGetter2(secondaryKey, type.element.library);
644643
if (getter == null) {
645-
throw MustachioResolutionError(node.keySpan.message(
644+
throw MustachioResolutionException(node.keySpan.message(
646645
"Failed to resolve '$secondaryKey' on ${context.type} while "
647646
'resolving $remainingNames as a property chain on any types in '
648647
'the context chain: $contextChain, after first resolving '

0 commit comments

Comments
 (0)