blob: a59366a83ea0b20f4563b524402d4394566c4172 [file] [log] [blame]
// Copyright (c) 2014, 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.
/// Library for debugging helpers. The unittest analyze_unused_test checks that
/// the helper are not used in production code.
library dart2js.helpers;
import '../common.dart';
import '../diagnostics/invariant.dart' show DEBUG_MODE;
import '../util/util.dart';
export 'debug_collection.dart';
export 'expensive_map.dart';
export 'expensive_set.dart';
export 'stats.dart';
export 'trace.dart';
export 'track_map.dart';
/// Global flag to enable [debugPrint]. This should always be `true` by default
/// and be set to `false` as a means to temporarily turn off all debugging
/// printouts.
const bool DEBUG_PRINT_ENABLED = true;
/// Enables debug mode.
///
/// Sets the [DEBUG_MODE] to `true`.
void enableDebugMode() {
DEBUG_MODE = true;
}
class _DebugIndentation extends Indentation {
@override
final String indentationUnit = " ";
}
_DebugIndentation _indentation = new _DebugIndentation();
/// Function signature of [debugPrint].
typedef DebugPrint(s);
/// If [DEBUG_PRINT_ENABLED] is `true` print [s] using the current indentation.
DebugPrint get debugPrint {
enableDebugMode();
// TODO(johnniwinther): Maybe disable debug mode after the call.
return _debugPrint;
}
/// Implementation of [debugPrint].
_debugPrint(s) {
if (DEBUG_PRINT_ENABLED) print('${_indentation.indentation}$s');
}
/// Function signature of [debugWrapPrint].
typedef DebugWrapPrint(s, f());
/// Wraps the call to [f] with a print of 'start:$s' and 'end:$s' incrementing
/// the current indentation used by [debugPrint] during the execution of [f].
///
/// Use this to get a tree-like debug printout for nested calls.
DebugWrapPrint get debugWrapPrint {
enableDebugMode();
return _debugWrapPrint;
}
/// Implementation of [debugWrapPrint].
_debugWrapPrint(s, f()) {
debugPrint('start:$s');
var result = _indentation.indentBlock(f);
debugPrint('end:$s');
return result;
}
/// Dummy method to mark breakpoints.
debugBreak() {
enableDebugMode();
}
/// Function signature of [reportHere].
typedef ReportHere(
DiagnosticReporter reporter, Spannable node, String debugMessage);
/// Print a message with a source location.
ReportHere get reportHere {
enableDebugMode();
return _reportHere;
}
/// Implementation of [reportHere]
_reportHere(DiagnosticReporter reporter, Spannable node, String debugMessage) {
reporter.reportInfoMessage(
node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
}
/// Set of tracked objects used by [track] and [ifTracked].
var _trackedObjects = new Set<Object>();
/// Global default value for the `printTrace` option of [track] and [ifTracked].
bool trackWithTrace = false;
/// If [doTrack] is `true`, add [object] to the set of tracked objects.
///
/// If tracked, [message] is printed along the hash code and toString of
/// [object]. If [printTrace] is `true` a trace printed additionally.
/// If [printTrace] is `null`, [trackWithTrace] determines whether a trace is
/// printed.
///
/// [object] is returned as the result of the method.
track(bool doTrack, Object object, String message, {bool printTrace}) {
if (!doTrack) return object;
_trackedObjects.add(object);
String msg = 'track: ${object.hashCode}:$object:$message';
if (printTrace == null) printTrace = trackWithTrace;
if (printTrace) {
trace(msg);
} else {
debugPrint(msg);
}
return object;
}
/// Returns `true` if [object] is in the set of tracked objects.
///
/// If [message] is provided it is printed along the hash code and toString of
/// [object]. If [printTrace] is `true` a trace printed additionally. If
/// [printTrace] is `null`, [trackWithTrace] determines whether a trace is
/// printed.
bool ifTracked(Object object, {String message, bool printTrace}) {
if (_trackedObjects.contains(object)) {
if (message != null) {
String msg = 'tracked: ${object.hashCode}:$object:$message';
if (printTrace == null) printTrace = trackWithTrace;
if (printTrace) {
trace(msg);
} else {
debugPrint(msg);
}
}
return true;
}
return false;
}