| // Copyright (c) 2012, 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'; | |
| import 'preprocessor_options.dart'; | |
| enum MessageLevel { info, warning, severe } | |
| // TODO(#159): Remove the global messages, use some object that tracks | |
| // compilation state. | |
| /// The global [Messages] for tracking info/warnings/messages. | |
| late Messages messages; | |
| // Color constants used for generating messages. | |
| const _greenColor = '\u001b[32m'; | |
| const _redColor = '\u001b[31m'; | |
| const _magentaColor = '\u001b[35m'; | |
| const _noColor = '\u001b[0m'; | |
| /// Map between error levels and their display color. | |
| const Map<MessageLevel, String> _errorColors = { | |
| MessageLevel.severe: _redColor, | |
| MessageLevel.warning: _magentaColor, | |
| MessageLevel.info: _greenColor, | |
| }; | |
| /// Map between error levels and their friendly name. | |
| const Map<MessageLevel, String> _errorLabel = { | |
| MessageLevel.severe: 'error', | |
| MessageLevel.warning: 'warning', | |
| MessageLevel.info: 'info', | |
| }; | |
| /// A single message from the compiler. | |
| class Message { | |
| final MessageLevel level; | |
| final String message; | |
| final SourceSpan? span; | |
| final bool useColors; | |
| Message(this.level, this.message, {this.span, this.useColors = false}); | |
| String get describe { | |
| var span = this.span; | |
| if (span == null) { | |
| return message; | |
| } | |
| var start = span.start; | |
| return '${start.line + 1}:${start.column + 1}:$message'; | |
| } | |
| @override | |
| String toString() { | |
| var output = StringBuffer(); | |
| var colors = useColors && _errorColors.containsKey(level); | |
| var levelColor = colors ? _errorColors[level] : null; | |
| if (colors) output.write(levelColor); | |
| output | |
| ..write(_errorLabel[level]) | |
| ..write(' '); | |
| if (colors) output.write(_noColor); | |
| if (span == null) { | |
| output.write(message); | |
| } else { | |
| output.write('on '); | |
| output.write(span!.message(message, color: levelColor)); | |
| } | |
| return output.toString(); | |
| } | |
| } | |
| /// This class tracks and prints information, warnings, and errors emitted by | |
| /// the compiler. | |
| class Messages { | |
| /// Called on every error. Set to blank function to suppress printing. | |
| final void Function(Message obj) printHandler; | |
| final PreprocessorOptions options; | |
| final List<Message> messages = <Message>[]; | |
| Messages({PreprocessorOptions? options, this.printHandler = print}) | |
| : options = options ?? const PreprocessorOptions(); | |
| /// Report a compile-time CSS error. | |
| void error(String message, SourceSpan? span) { | |
| var msg = Message(MessageLevel.severe, message, | |
| span: span, useColors: options.useColors); | |
| messages.add(msg); | |
| printHandler(msg); | |
| } | |
| /// Report a compile-time CSS warning. | |
| void warning(String message, SourceSpan? span) { | |
| if (options.warningsAsErrors) { | |
| error(message, span); | |
| } else { | |
| var msg = Message(MessageLevel.warning, message, | |
| span: span, useColors: options.useColors); | |
| messages.add(msg); | |
| } | |
| } | |
| /// Report and informational message about what the compiler is doing. | |
| void info(String message, SourceSpan span) { | |
| var msg = Message(MessageLevel.info, message, | |
| span: span, useColors: options.useColors); | |
| messages.add(msg); | |
| if (options.verbose) printHandler(msg); | |
| } | |
| /// Merge [newMessages] to this message list. | |
| void mergeMessages(Messages newMessages) { | |
| messages.addAll(newMessages.messages); | |
| newMessages.messages | |
| .where((message) => | |
| message.level == MessageLevel.severe || options.verbose) | |
| .forEach(printHandler); | |
| } | |
| } |