mirror of
https://github.com/danog/dart-sass.git
synced 2025-01-22 22:02:00 +01:00
Emit LogEvents (#6)
This commit is contained in:
parent
3de78be2f0
commit
ec05600af2
@ -7,12 +7,11 @@ import 'dart:convert';
|
||||
|
||||
import 'package:sass/sass.dart' as sass;
|
||||
import 'package:source_maps/source_maps.dart' as source_maps;
|
||||
import 'package:source_span/source_span.dart';
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
|
||||
import 'package:sass_embedded/src/dispatcher.dart';
|
||||
import 'package:sass_embedded/src/embedded_sass.pb.dart' as proto;
|
||||
import 'package:sass_embedded/src/embedded_sass.pb.dart' hide SourceSpan;
|
||||
import 'package:sass_embedded/src/embedded_sass.pb.dart';
|
||||
import 'package:sass_embedded/src/logger.dart';
|
||||
import 'package:sass_embedded/src/util/length_delimited_transformer.dart';
|
||||
import 'package:sass_embedded/src/utils.dart';
|
||||
|
||||
@ -35,6 +34,7 @@ void main(List<String> args) {
|
||||
request.style == InboundMessage_CompileRequest_OutputStyle.COMPRESSED
|
||||
? sass.OutputStyle.compressed
|
||||
: sass.OutputStyle.expanded;
|
||||
var logger = Logger(dispatcher, request.id);
|
||||
|
||||
try {
|
||||
String result;
|
||||
@ -46,6 +46,7 @@ void main(List<String> args) {
|
||||
case InboundMessage_CompileRequest_Input.string:
|
||||
var input = request.string;
|
||||
result = sass.compileString(input.source,
|
||||
logger: logger,
|
||||
syntax: _syntaxToSyntax(input.syntax),
|
||||
style: style,
|
||||
url: input.url.isEmpty ? null : input.url,
|
||||
@ -55,7 +56,7 @@ void main(List<String> args) {
|
||||
case InboundMessage_CompileRequest_Input.path:
|
||||
try {
|
||||
result = sass.compile(request.path,
|
||||
style: style, sourceMap: sourceMapCallback);
|
||||
logger: logger, style: style, sourceMap: sourceMapCallback);
|
||||
} on FileSystemException catch (error) {
|
||||
return OutboundMessage_CompileResponse()
|
||||
..failure = (OutboundMessage_CompileResponse_CompileFailure()
|
||||
@ -79,7 +80,7 @@ void main(List<String> args) {
|
||||
return OutboundMessage_CompileResponse()
|
||||
..failure = (OutboundMessage_CompileResponse_CompileFailure()
|
||||
..message = error.message
|
||||
..span = _protofySpan(error.span)
|
||||
..span = protofySpan(error.span)
|
||||
..stackTrace = error.trace.toString());
|
||||
}
|
||||
});
|
||||
@ -98,18 +99,3 @@ sass.Syntax _syntaxToSyntax(InboundMessage_Syntax syntax) {
|
||||
throw "Unknown syntax $syntax.";
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a Dart source span to a protocol buffer source span.
|
||||
proto.SourceSpan _protofySpan(SourceSpanWithContext span) => proto.SourceSpan()
|
||||
..text = span.text
|
||||
..start = _protofyLocation(span.start)
|
||||
..end = _protofyLocation(span.end)
|
||||
..url = span.sourceUrl?.toString() ?? ""
|
||||
..context = span.context;
|
||||
|
||||
/// Converts a Dart source location to a protocol buffer source location.
|
||||
SourceSpan_SourceLocation _protofyLocation(SourceLocation location) =>
|
||||
SourceSpan_SourceLocation()
|
||||
..offset = location.offset
|
||||
..line = location.line
|
||||
..column = location.column;
|
||||
|
@ -90,6 +90,10 @@ class Dispatcher {
|
||||
});
|
||||
}
|
||||
|
||||
/// Sends [event] to the host.
|
||||
void sendLog(OutboundMessage_LogEvent event) =>
|
||||
_send(OutboundMessage()..logEvent = event);
|
||||
|
||||
/// Sends [message] to the host.
|
||||
void _send(OutboundMessage message) =>
|
||||
_channel.sink.add(message.writeToBuffer());
|
||||
|
43
lib/src/logger.dart
Normal file
43
lib/src/logger.dart
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2019 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 'package:sass/sass.dart' as sass;
|
||||
import 'package:source_span/source_span.dart';
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
import 'dispatcher.dart';
|
||||
import 'embedded_sass.pb.dart' hide SourceSpan;
|
||||
import 'utils.dart';
|
||||
|
||||
/// A Sass logger that sends log messages as `LogEvent`s.
|
||||
class Logger implements sass.Logger {
|
||||
/// The [Dispatcher] to which to send events.
|
||||
final Dispatcher _dispatcher;
|
||||
|
||||
/// The ID of the compilation to which this logger is passed.
|
||||
final int _compilationId;
|
||||
|
||||
Logger(this._dispatcher, this._compilationId);
|
||||
|
||||
void debug(String message, SourceSpan span) {
|
||||
_dispatcher.sendLog(OutboundMessage_LogEvent()
|
||||
..compilationId = _compilationId
|
||||
..type = OutboundMessage_LogEvent_Type.DEBUG
|
||||
..message = message
|
||||
..span = protofySpan(span));
|
||||
}
|
||||
|
||||
void warn(String message,
|
||||
{FileSpan span, Trace trace, bool deprecation = false}) {
|
||||
var event = OutboundMessage_LogEvent()
|
||||
..compilationId = _compilationId
|
||||
..type = deprecation
|
||||
? OutboundMessage_LogEvent_Type.DEPRECATION_WARNING
|
||||
: OutboundMessage_LogEvent_Type.WARNING
|
||||
..message = message;
|
||||
if (span != null) event.span = protofySpan(span);
|
||||
if (trace != null) event.stackTrace = trace.toString();
|
||||
_dispatcher.sendLog(event);
|
||||
}
|
||||
}
|
@ -2,10 +2,31 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'embedded_sass.pb.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import 'embedded_sass.pb.dart' as proto;
|
||||
import 'embedded_sass.pb.dart' hide SourceSpan;
|
||||
|
||||
/// Returns a [ProtocolError] indicating that a mandatory field with the givne
|
||||
/// [fieldName] was missing.
|
||||
ProtocolError mandatoryError(String fieldName) => ProtocolError()
|
||||
..type = ProtocolError_ErrorType.PARAMS
|
||||
..message = "Missing mandatory field $fieldName";
|
||||
|
||||
/// Converts a Dart source span to a protocol buffer source span.
|
||||
proto.SourceSpan protofySpan(SourceSpan span) {
|
||||
var protoSpan = proto.SourceSpan()
|
||||
..text = span.text
|
||||
..start = _protofyLocation(span.start)
|
||||
..end = _protofyLocation(span.end)
|
||||
..url = span.sourceUrl?.toString() ?? "";
|
||||
if (span is SourceSpanWithContext) protoSpan.context = span.context;
|
||||
return protoSpan;
|
||||
}
|
||||
|
||||
/// Converts a Dart source location to a protocol buffer source location.
|
||||
SourceSpan_SourceLocation _protofyLocation(SourceLocation location) =>
|
||||
SourceSpan_SourceLocation()
|
||||
..offset = location.offset
|
||||
..line = location.line
|
||||
..column = location.column;
|
||||
|
@ -155,6 +155,85 @@ void main() {
|
||||
await process.kill();
|
||||
});
|
||||
|
||||
group("emits a log event", () {
|
||||
test("for a @debug rule", () async {
|
||||
process.inbound.add(compileString("a {@debug hello}"));
|
||||
|
||||
var logEvent = getLogEvent(await process.outbound.next);
|
||||
expect(logEvent.compilationId, equals(0));
|
||||
expect(logEvent.type, equals(OutboundMessage_LogEvent_Type.DEBUG));
|
||||
expect(logEvent.message, equals("hello"));
|
||||
expect(logEvent.span.text, equals("@debug hello"));
|
||||
expect(logEvent.span.start, equals(location(3, 0, 3)));
|
||||
expect(logEvent.span.end, equals(location(15, 0, 15)));
|
||||
expect(logEvent.span.context, equals("a {@debug hello}"));
|
||||
expect(logEvent.stackTrace, isEmpty);
|
||||
await process.kill();
|
||||
});
|
||||
|
||||
test("for a @warn rule", () async {
|
||||
process.inbound.add(compileString("a {@warn hello}"));
|
||||
|
||||
var logEvent = getLogEvent(await process.outbound.next);
|
||||
expect(logEvent.compilationId, equals(0));
|
||||
expect(logEvent.type, equals(OutboundMessage_LogEvent_Type.WARNING));
|
||||
expect(logEvent.message, equals("hello"));
|
||||
expect(logEvent.span, equals(SourceSpan()));
|
||||
expect(logEvent.stackTrace, equals("- 1:4 root stylesheet\n"));
|
||||
await process.kill();
|
||||
});
|
||||
|
||||
test("for a parse-time deprecation warning", () async {
|
||||
process.inbound.add(compileString("@if true {} @elseif true {}"));
|
||||
|
||||
var logEvent = getLogEvent(await process.outbound.next);
|
||||
expect(logEvent.compilationId, equals(0));
|
||||
expect(logEvent.type,
|
||||
equals(OutboundMessage_LogEvent_Type.DEPRECATION_WARNING));
|
||||
expect(
|
||||
logEvent.message,
|
||||
equals(
|
||||
'@elseif is deprecated and will not be supported in future Sass '
|
||||
'versions.\n'
|
||||
'Use "@else if" instead.'));
|
||||
expect(logEvent.span.text, equals("@elseif"));
|
||||
expect(logEvent.span.start, equals(location(12, 0, 12)));
|
||||
expect(logEvent.span.end, equals(location(19, 0, 19)));
|
||||
expect(logEvent.span.context, equals("@if true {} @elseif true {}"));
|
||||
expect(logEvent.stackTrace, isEmpty);
|
||||
await process.kill();
|
||||
});
|
||||
|
||||
test("for a runtime deprecation warning", () async {
|
||||
process.inbound.add(compileString("a {\$var: value !global}"));
|
||||
|
||||
var logEvent = getLogEvent(await process.outbound.next);
|
||||
expect(logEvent.compilationId, equals(0));
|
||||
expect(logEvent.type,
|
||||
equals(OutboundMessage_LogEvent_Type.DEPRECATION_WARNING));
|
||||
expect(
|
||||
logEvent.message,
|
||||
equals("As of Dart Sass 2.0.0, !global assignments won't be able to\n"
|
||||
"declare new variables. Consider adding `\$var: null` at the "
|
||||
"root of the\n"
|
||||
"stylesheet."));
|
||||
expect(logEvent.span.text, equals("\$var: value !global"));
|
||||
expect(logEvent.span.start, equals(location(3, 0, 3)));
|
||||
expect(logEvent.span.end, equals(location(22, 0, 22)));
|
||||
expect(logEvent.span.context, equals("a {\$var: value !global}"));
|
||||
expect(logEvent.stackTrace, "- 1:4 root stylesheet\n");
|
||||
await process.kill();
|
||||
});
|
||||
|
||||
test("with the same ID as the CompileRequest", () async {
|
||||
process.inbound.add(compileString("@debug hello", id: 12345));
|
||||
|
||||
var logEvent = getLogEvent(await process.outbound.next);
|
||||
expect(logEvent.compilationId, equals(12345));
|
||||
await process.kill();
|
||||
});
|
||||
});
|
||||
|
||||
group("gracefully handles an error", () {
|
||||
test("from invalid syntax", () async {
|
||||
process.inbound.add(compileString("a {b: }"));
|
||||
|
@ -90,7 +90,8 @@ void _ensureUpToDate(String path, String commandToRun) {
|
||||
/// Returns a [InboundMessage] that compiles the given plain CSS
|
||||
/// string.
|
||||
InboundMessage compileString(String css,
|
||||
{InboundMessage_Syntax syntax,
|
||||
{int id,
|
||||
InboundMessage_Syntax syntax,
|
||||
InboundMessage_CompileRequest_OutputStyle style,
|
||||
String url,
|
||||
bool sourceMap}) {
|
||||
@ -99,6 +100,7 @@ InboundMessage compileString(String css,
|
||||
if (url != null) input.url = url;
|
||||
|
||||
var request = InboundMessage_CompileRequest()..string = input;
|
||||
if (id != null) request.id = id;
|
||||
if (style != null) request.style = style;
|
||||
if (sourceMap != null) request.sourceMap = sourceMap;
|
||||
|
||||
@ -146,6 +148,16 @@ OutboundMessage_CompileResponse getCompileResponse(value) {
|
||||
return message.compileResponse;
|
||||
}
|
||||
|
||||
/// Asserts that [message] is an [OutboundMessage] with a `LogEvent` and
|
||||
/// returns it.
|
||||
OutboundMessage_LogEvent getLogEvent(value) {
|
||||
expect(value, isA<OutboundMessage>());
|
||||
var message = value as OutboundMessage;
|
||||
expect(message.hasLogEvent(), isTrue,
|
||||
reason: "Expected $message to have a LogEvent");
|
||||
return message.logEvent;
|
||||
}
|
||||
|
||||
/// Asserts that an [OutboundMessage] is a `CompileResponse` with CSS that
|
||||
/// matches [css], with a source map that matches [sourceMap] (if passed).
|
||||
///
|
||||
|
Loading…
x
Reference in New Issue
Block a user