Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/src/embedded/compilation_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:sass/sass.dart' as sass;
import 'package:sass/src/importer/node_package.dart' as npi;

import '../logger.dart';
import '../util/trace.dart';
import '../value/function.dart';
import '../value/mixin.dart';
import 'embedded_sass.pb.dart';
Expand Down Expand Up @@ -241,14 +242,14 @@ final class CompilationDispatcher {
..loadedUrls.addAll(result.loadedUrls.map((url) => url.toString()));
} on sass.SassException catch (error) {
var formatted = withGlyphs(
() => error.toString(color: request.alertColor),
() => error.toString(color: request.alertColor, prettyUri: false),
ascii: request.alertAscii,
);
return OutboundMessage_CompileResponse()
..failure = (OutboundMessage_CompileResponse_CompileFailure()
..message = error.message
..span = protofySpan(error.span)
..stackTrace = error.trace.toString()
..stackTrace = error.trace.printString(prettyUri: false)
..formatted = formatted)
..loadedUrls.addAll(error.loadedUrls.map((url) => url.toString()));
}
Expand Down
12 changes: 7 additions & 5 deletions lib/src/embedded/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

import '../deprecation.dart';
import '../logger.dart';
import '../util/nullable.dart';
import '../util/trace.dart';
import '../utils.dart';
import 'compilation_dispatcher.dart';
import 'embedded_sass.pb.dart' hide SourceSpan;
Expand All @@ -35,7 +34,9 @@ final class EmbeddedLogger extends LoggerWithDeprecationType {
..type = LogEventType.DEBUG
..message = message
..span = protofySpan(span)
..formatted = (span.start.sourceUrl.andThen(p.prettyUri) ?? '-') +
..formatted = (span.start.sourceUrl == null
? '-'
: span.start.sourceUrl.toString()) +
':${span.start.line + 1} ' +
(_color ? '\u001b[1mDebug\u001b[0m' : 'DEBUG') +
': $message\n',
Expand Down Expand Up @@ -70,7 +71,8 @@ final class EmbeddedLogger extends LoggerWithDeprecationType {
buffer.writeln(' on ${span.message("\n" + message, color: _color)}');
}
if (trace != null) {
buffer.writeln(indent(trace.toString().trimRight(), 4));
buffer.writeln(
indent(trace.printString(prettyUri: false).trimRight(), 4));
}
return buffer.toString();
}, ascii: _ascii);
Expand All @@ -82,7 +84,7 @@ final class EmbeddedLogger extends LoggerWithDeprecationType {
..message = message
..formatted = formatted;
if (span != null) event.span = protofySpan(span);
if (trace != null) event.stackTrace = trace.toString();
if (trace != null) event.stackTrace = trace.printString(prettyUri: false);
if (deprecation != null) event.deprecationType = deprecation.id;
_dispatcher.sendLog(event);
}
Expand Down
10 changes: 6 additions & 4 deletions lib/src/exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:stack_trace/stack_trace.dart';
import 'package:term_glyph/term_glyph.dart' as term_glyph;

import 'util/nullable.dart';
import 'util/trace.dart';
import 'utils.dart';
import 'value.dart';

Expand Down Expand Up @@ -53,12 +54,12 @@ class SassException extends SourceSpanException {
SassException withLoadedUrls(Iterable<Uri> loadedUrls) =>
SassException(message, span, loadedUrls);

String toString({Object? color}) {
String toString({Object? color, bool prettyUri = true}) {
var buffer = StringBuffer()
..writeln("Error: $message")
..write(span.highlight(color: color));

for (var frame in trace.toString().split("\n")) {
for (var frame in trace.printString(prettyUri: prettyUri).split("\n")) {
if (frame.isEmpty) continue;
buffer.writeln();
buffer.write(" $frame");
Expand Down Expand Up @@ -158,7 +159,8 @@ class MultiSpanSassException extends SassException
loadedUrls,
);

String toString({Object? color, String? secondaryColor}) {
String toString(
{Object? color, String? secondaryColor, bool prettyUri = true}) {
var useColor = false;
String? primaryColor;
if (color is String) {
Expand All @@ -180,7 +182,7 @@ class MultiSpanSassException extends SassException
)
.andThen(buffer.write);

for (var frame in trace.toString().split("\n")) {
for (var frame in trace.printString(prettyUri: prettyUri).split("\n")) {
if (frame.isEmpty) continue;
buffer.writeln();
buffer.write(" $frame");
Expand Down
47 changes: 47 additions & 0 deletions lib/src/util/trace.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2026 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'dart:math' as math;

import 'package:stack_trace/stack_trace.dart';

/// Extensions for printing Trace
extension TraceExtensions on Trace {
/// Returns a human-readable representation of this trace.
///
/// This will not use `path.prettyUri()` when [prettyUri] is false.
String printString({bool prettyUri = true}) {
if (prettyUri) return toString();

// Figure out the longest path so we know how much to pad.
var longest =
frames.map((frame) => frame._location.length).fold(0, math.max);

// Print out the stack trace nicely formatted.
return frames.map((frame) {
if (frame is UnparsedFrame) return '$frame\n';
return '${frame._location.padRight(longest)} ${frame.member}\n';
}).join();
}
}

/// Extensions for printing Frame
extension FrameExtensions on Frame {
/// Returns a human-friendly description of the library that this stack frame
/// comes from.
///
/// This will usually be the string form of [uri]. Absolute URIs will not be
/// converted to relative URIs. Data URIs will be truncated.
String get _library {
if (uri.scheme == 'data') return 'data:...';
return uri.toString();
}

/// A human-friendly description of the code location.
String get _location {
if (line == null) return _library;
if (column == null) return '$_library $line';
return '$_library $line:$column';
}
}
3 changes: 2 additions & 1 deletion test/embedded/protocol_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,8 @@ void main() {
var failure = await getCompileFailure(process);
expect(p.fromUri(failure.span.url), equalsPath(path));
expect(failure.stackTrace, endsWith(" 1:7 root stylesheet\n"));
expect(failure.stackTrace.split(" ").first, equalsPath(path));
expect(
p.fromUri(failure.stackTrace.split(" ").first), equalsPath(path));
await process.close();
});
});
Expand Down
Loading