b5eabedd8f
This makes it possible for calling code to get the error message without the stack trace, if it so desires. R=rnystrom@google.com Review URL: https://codereview.chromium.org//307543006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36724 260f80e4-7a28-3924-810f-c04153c831b5
193 lines
6.2 KiB
Dart
193 lines
6.2 KiB
Dart
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library barback.errors;
|
|
|
|
import 'package:stack_trace/stack_trace.dart';
|
|
|
|
import 'asset/asset_id.dart';
|
|
import 'transformer/wrapping_aggregate_transformer.dart';
|
|
import 'utils.dart';
|
|
|
|
/// Error thrown when an asset with [id] cannot be found.
|
|
class AssetNotFoundException implements Exception {
|
|
final AssetId id;
|
|
|
|
AssetNotFoundException(this.id);
|
|
|
|
String toString() => "Could not find asset $id.";
|
|
}
|
|
|
|
/// Replaces any occurrences of [AggregateException] in [errors] with the list
|
|
/// of errors it contains.
|
|
Iterable<BarbackException> flattenAggregateExceptions(
|
|
Iterable<BarbackException> errors) {
|
|
return errors.expand((error) {
|
|
if (error is! AggregateException) return [error];
|
|
return error.errors;
|
|
});
|
|
}
|
|
|
|
/// The interface for exceptions from the barback graph or its transformers.
|
|
///
|
|
/// These exceptions are never produced by programming errors in barback.
|
|
abstract class BarbackException implements Exception {
|
|
/// Takes a collection of [BarbackExceptions] and returns a single exception
|
|
/// that contains them all.
|
|
///
|
|
/// If [errors] is empty, returns `null`. If it only has one error, that
|
|
/// error is returned. Otherwise, an [AggregateException] is returned.
|
|
static BarbackException aggregate(Iterable<BarbackException> errors) {
|
|
if (errors.isEmpty) return null;
|
|
if (errors.length == 1) return errors.single;
|
|
return new AggregateException(errors);
|
|
}
|
|
}
|
|
|
|
/// An error that wraps a collection of other [BarbackException]s.
|
|
///
|
|
/// It implicitly flattens any [AggregateException]s that occur in the list of
|
|
/// exceptions it wraps.
|
|
class AggregateException implements BarbackException {
|
|
final Set<BarbackException> errors;
|
|
|
|
AggregateException(Iterable<BarbackException> errors)
|
|
: errors = flattenAggregateExceptions(errors).toSet();
|
|
|
|
String toString() {
|
|
var buffer = new StringBuffer();
|
|
buffer.writeln("Multiple errors occurred:\n");
|
|
|
|
for (var error in errors) {
|
|
buffer.writeln(prefixLines(error.toString(),
|
|
prefix: " ", firstPrefix: "- "));
|
|
}
|
|
|
|
return buffer.toString();
|
|
}
|
|
}
|
|
|
|
/// Error thrown when two or more transformers both output an asset with [id].
|
|
class AssetCollisionException implements BarbackException {
|
|
/// All the transforms that output an asset with [id].
|
|
///
|
|
/// If this only contains a single transform, that indicates that a
|
|
/// transformer produced an output that collides with a source asset or an
|
|
/// asset from a previous phase.
|
|
final Set<TransformInfo> transforms;
|
|
final AssetId id;
|
|
|
|
AssetCollisionException(Iterable<TransformInfo> transforms, this.id)
|
|
: transforms = new Set.from(transforms);
|
|
|
|
String toString() => "Transforms $transforms all emitted asset $id.";
|
|
}
|
|
|
|
/// Error thrown when a transformer requests an input [id] which cannot be
|
|
/// found.
|
|
class MissingInputException implements BarbackException {
|
|
/// The transform that requested [id].
|
|
final TransformInfo transform;
|
|
final AssetId id;
|
|
|
|
MissingInputException(this.transform, this.id);
|
|
|
|
String toString() => "Transform $transform tried to load missing input $id.";
|
|
}
|
|
|
|
/// Error thrown when a transformer outputs an asset to a different package than
|
|
/// the primary input's.
|
|
class InvalidOutputException implements BarbackException {
|
|
/// The transform that output the asset.
|
|
final TransformInfo transform;
|
|
final AssetId id;
|
|
|
|
InvalidOutputException(this.transform, this.id);
|
|
|
|
String toString() => "Transform $transform emitted $id, which wasn't in the "
|
|
"same package (${transform.primaryId.package}).";
|
|
}
|
|
|
|
/// Base class for an error that wraps another.
|
|
abstract class _WrappedException implements BarbackException {
|
|
/// The wrapped exception.
|
|
final error;
|
|
final Chain stackTrace;
|
|
|
|
String get message => "$_message: ${getErrorMessage(error)}";
|
|
|
|
String get _message;
|
|
|
|
_WrappedException(error, StackTrace stackTrace)
|
|
: this.error = error,
|
|
this.stackTrace = _getChain(error, stackTrace);
|
|
|
|
String toString() {
|
|
var result = message;
|
|
if (stackTrace != null) result = "$result\n${stackTrace.terse}";
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// Returns the stack chain for [error] and [stackTrace].
|
|
Chain _getChain(error, StackTrace stackTrace) {
|
|
if (error is Error && stackTrace == null) stackTrace = error.stackTrace;
|
|
if (stackTrace != null) return new Chain.forTrace(stackTrace);
|
|
return null;
|
|
}
|
|
|
|
/// Error wrapping an exception thrown by a transform.
|
|
class TransformerException extends _WrappedException {
|
|
/// The transform that threw the exception.
|
|
final TransformInfo transform;
|
|
|
|
TransformerException(this.transform, error, StackTrace stackTrace)
|
|
: super(error, stackTrace);
|
|
|
|
String get _message => "Transform $transform threw error";
|
|
}
|
|
|
|
/// Error thrown when a source asset [id] fails to load.
|
|
///
|
|
/// This can be thrown either because the source asset was expected to exist and
|
|
/// did not or because reading it failed somehow.
|
|
class AssetLoadException extends _WrappedException {
|
|
final AssetId id;
|
|
|
|
AssetLoadException(this.id, error, [StackTrace stackTrace])
|
|
: super(error, stackTrace);
|
|
|
|
String get _message => "Failed to load source asset $id";
|
|
}
|
|
|
|
/// Information about a single transform in the barback graph.
|
|
///
|
|
/// Identifies a single transformation in the barback graph.
|
|
///
|
|
/// A transformation is uniquely identified by the ID of its primary input, and
|
|
/// the transformer that is applied to it.
|
|
class TransformInfo {
|
|
/// The transformer that's run for this transform.
|
|
///
|
|
/// This may be a [Transformer] or a [WrappingAggregateTransformer]. It may
|
|
/// also return additional types in the future.
|
|
final transformer;
|
|
|
|
/// The id of this transform's primary asset.
|
|
final AssetId primaryId;
|
|
|
|
TransformInfo(transformer, this.primaryId)
|
|
: transformer = transformer is WrappingAggregateTransformer ?
|
|
transformer.transformer : transformer;
|
|
|
|
bool operator==(other) =>
|
|
other is TransformInfo &&
|
|
other.transformer == transformer &&
|
|
other.primaryId == primaryId;
|
|
|
|
int get hashCode => transformer.hashCode ^ primaryId.hashCode;
|
|
|
|
String toString() => "$transformer on $primaryId";
|
|
}
|