| // 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. |
| |
| /** The one true [World]. */ |
| World world; |
| |
| typedef void MessageHandler(String prefix, String message, SourceSpan span); |
| typedef void PrintHandler(String message); |
| |
| /** |
| * Should be called exactly once to setup singleton world. |
| * Can use world.reset() to reinitialize. |
| */ |
| void initializeWorld(var files) { |
| assert(world == null); |
| world = new World(files); |
| world.init(); |
| } |
| |
| /** Can be thrown on any compiler error and includes source location. */ |
| class CompilerException implements Exception { |
| final String _message; |
| final SourceSpan _location; |
| |
| CompilerException(this._message, this._location); |
| |
| String toString() { |
| if (_location != null) { |
| return 'CompilerException: ${_location.toMessageString(_message)}'; |
| } else { |
| return 'CompilerException: $_message'; |
| } |
| } |
| } |
| |
| /** Represents a Dart template "world". */ |
| class World { |
| String template; |
| |
| var files; |
| |
| int errors = 0, warnings = 0; |
| bool seenFatal = false; |
| MessageHandler messageHandler; |
| PrintHandler printHandler; |
| |
| World(this.files); |
| |
| void reset() { |
| errors = warnings = 0; |
| seenFatal = false; |
| init(); |
| } |
| |
| init() { |
| } |
| |
| |
| // ********************** Message support *********************** |
| |
| void _message(String color, String prefix, String message, |
| SourceSpan span, SourceSpan span1, SourceSpan span2, bool throwing) { |
| if (messageHandler != null) { |
| // TODO(jimhug): Multiple spans cleaner... |
| messageHandler(prefix, message, span); |
| if (span1 != null) { |
| messageHandler(prefix, message, span1); |
| } |
| if (span2 != null) { |
| messageHandler(prefix, message, span2); |
| } |
| } else { |
| final messageWithPrefix = options.useColors |
| ? "$color$prefix$_NO_COLOR$message" : "$prefix$message"; |
| |
| var text = messageWithPrefix; |
| if (span != null) { |
| text = span.toMessageString(messageWithPrefix); |
| } |
| |
| String span1Text = span1 != null ? |
| span1.toMessageString(messageWithPrefix) : ""; |
| String span2Text = span2 != null ? |
| span2.toMessageString(messageWithPrefix) : ""; |
| |
| if (printHandler == null) { |
| print(text); |
| if (span1 != null) { |
| print(span1Text); |
| } |
| if (span2 != null) { |
| print(span2Text); |
| } |
| } else { |
| printHandler("${text}\r${span1Text}\r${span2Text}"); |
| } |
| } |
| |
| if (throwing) { |
| throw new CompilerException("$prefix$message", span); |
| } |
| } |
| |
| /** [message] is considered a static compile-time error by the Dart lang. */ |
| void error(String message, |
| [SourceSpan span, SourceSpan span1, SourceSpan span2]) { |
| errors++; |
| _message(_RED_COLOR, 'error: ', message, |
| span, span1, span2, options.throwOnErrors); |
| } |
| |
| /** [message] is considered a type warning by the Dart lang. */ |
| void warning(String message, |
| [SourceSpan span, SourceSpan span1, SourceSpan span2]) { |
| if (options.warningsAsErrors) { |
| error(message, span, span1, span2); |
| return; |
| } |
| warnings++; |
| if (options.showWarnings) { |
| _message(_MAGENTA_COLOR, 'warning: ', message, |
| span, span1, span2, options.throwOnWarnings); |
| } |
| } |
| |
| /** [message] at [location] is so bad we can't generate runnable code. */ |
| void fatal(String message, |
| {SourceSpan span, SourceSpan span1, SourceSpan span2}) { |
| errors++; |
| seenFatal = true; |
| _message(_RED_COLOR, 'fatal: ', message, |
| span, span1, span2, options.throwOnFatal || options.throwOnErrors); |
| } |
| |
| /** [message] at [location] is about a bug in the compiler. */ |
| void internalError(String message, |
| {SourceSpan span, SourceSpan span1, SourceSpan span2}) { |
| _message(_NO_COLOR, |
| 'We are sorry, but...', message, span, span1, span2, true); |
| } |
| |
| /** |
| * [message] at [location] will tell the user about what the compiler |
| * is doing. |
| */ |
| void info(String message, |
| [SourceSpan span, SourceSpan span1, SourceSpan span2]) { |
| if (options.showInfo) { |
| _message(_GREEN_COLOR, 'info: ', message, span, span1, span2, false); |
| } |
| } |
| |
| bool get hasErrors => errors > 0; |
| |
| withTiming(String name, f()) { |
| final sw = new Stopwatch(); |
| sw.start(); |
| var result = f(); |
| sw.stop(); |
| info('$name in ${sw.elapsedMilliseconds}msec'); |
| return result; |
| } |
| } |
| |
| String _GREEN_COLOR = '\u001b[32m'; |
| String _RED_COLOR = '\u001b[31m'; |
| String _MAGENTA_COLOR = '\u001b[35m'; |
| String _NO_COLOR = '\u001b[0m'; |