blob: 8c3dc56c10d991de390b6e44e7eeb2af82a58b25 [file] [log] [blame] [edit]
// Copyright (c) 2025, 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.
import 'package:source_span/source_span.dart';
/// An error with an associated source span.
class LocatedError {
final SourceSpan span;
final String message;
LocatedError(this.message, {required this.span});
@override
String toString() => '${span.location}: $message';
/// Executes [callback], converting any exceptions it generates to a
/// [LocatedError] that points to [node].
static T wrap<T>(T Function() callback, {required SourceSpan span}) {
try {
return callback();
} catch (error, stackTrace) {
if (error is! LocatedError) {
Error.throwWithStackTrace(
LocatedError(error.toString(), span: span),
stackTrace,
);
} else {
rethrow;
}
}
}
}
extension SourceSpanLocation on SourceSpan {
/// A string suitable for identifying this span in the source YAML file.
String get location {
var path = start.sourceUrl?.toFilePath() ?? '<unknown>';
// Convert line/column to 1-based because that's what most editors expect
var line = start.line + 1;
var column = start.column + 1;
return '$path:$line:$column';
}
}