Enable travis, add analysis_options, other cleanup (#35)
* Fix strong-mode issues
* dartfmt
* Switch to triple-slash, @override, single quotes
* Enable Travis-CI
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1e1c46c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,29 @@
+language: dart
+sudo: false
+dart:
+ - dev
+ - stable
+
+dart_task:
+ - test: --platform vm
+ - test: --platform firefox
+ - test: --platform chrome
+ - test: --platform dartium
+ install_dartium: true
+
+matrix:
+ include:
+ - dart: dev
+ dart_task: dartfmt
+ - dart: dev
+ dart_task: dartanalyzer
+ - dart: stable
+ dart_task: dartanalyzer
+
+# Only building master means that we don't run two builds for each pull request.
+branches:
+ only: [master]
+
+cache:
+ directories:
+ - $HOME/.pub-cache
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..848b33f
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,38 @@
+analyzer:
+ strong-mode:
+ implicit-casts: false
+ errors:
+ unused_element: error
+ unused_import: error
+ unused_local_variable: error
+ dead_code: error
+linter:
+ rules:
+ - annotate_overrides
+ - avoid_empty_else
+ - avoid_init_to_null
+ - avoid_return_types_on_setters
+ - await_only_futures
+ - camel_case_types
+ - comment_references
+ - control_flow_in_finally
+ - directives_ordering
+ - empty_catches
+ - empty_constructor_bodies
+ - empty_statements
+ - hash_and_equals
+ - implementation_imports
+ - library_names
+ - library_prefixes
+ - non_constant_identifier_names
+ - only_throw_errors
+ - prefer_final_fields
+ - prefer_is_not_empty
+ - prefer_single_quotes
+ - slash_for_doc_comments
+ - test_types_in_equals
+ - test_types_in_equals
+ - throw_in_finally
+ - type_init_formals
+ - unrelated_type_equality_checks
+ - valid_regexps
diff --git a/lib/logging.dart b/lib/logging.dart
index 9a7e531..e278d76 100644
--- a/lib/logging.dart
+++ b/lib/logging.dart
@@ -2,8 +2,6 @@
// 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 logging;
import 'dart:async';
@@ -26,37 +24,33 @@
/// false.
Level _rootLevel = Level.INFO;
-/**
- * Use a [Logger] to log debug messages.
- *
- * [Logger]s are named using a hierarchical dot-separated name convention.
- */
+/// Use a [Logger] to log debug messages.
+///
+/// [Logger]s are named using a hierarchical dot-separated name convention.
class Logger {
- /** Simple name of this logger. */
+ /// Simple name of this logger.
final String name;
- /** The full name of this logger, which includes the parent's full name. */
+ /// The full name of this logger, which includes the parent's full name.
String get fullName =>
(parent == null || parent.name == '') ? name : '${parent.fullName}.$name';
- /** Parent of this logger in the hierarchy of loggers. */
+ /// Parent of this logger in the hierarchy of loggers.
final Logger parent;
- /** Logging [Level] used for entries generated on this logger. */
+ /// Logging [Level] used for entries generated on this logger.
Level _level;
final Map<String, Logger> _children;
- /** Children in the hierarchy of loggers, indexed by their simple names. */
+ /// Children in the hierarchy of loggers, indexed by their simple names.
final Map<String, Logger> children;
- /** Controller used to notify when log entries are added to this logger. */
+ /// Controller used to notify when log entries are added to this logger.
StreamController<LogRecord> _controller;
- /**
- * Singleton constructor. Calling `new Logger(name)` will return the same
- * actual instance whenever it is called with the same string name.
- */
+ /// Singleton constructor. Calling `new Logger(name)` will return the same
+ /// actual instance whenever it is called with the same string name.
factory Logger(String name) {
return _loggers.putIfAbsent(name, () => new Logger._named(name));
}
@@ -79,7 +73,7 @@
}
// Split hierarchical names (separated with '.').
int dot = name.lastIndexOf('.');
- Logger parent = null;
+ Logger parent;
String thisName;
if (dot == -1) {
if (name != '') parent = new Logger('');
@@ -97,10 +91,8 @@
if (parent != null) parent._children[name] = this;
}
- /**
- * Effective level considering the levels established in this logger's parents
- * (when [hierarchicalLoggingEnabled] is true).
- */
+ /// Effective level considering the levels established in this logger's
+ /// parents (when [hierarchicalLoggingEnabled] is true).
Level get level {
if (hierarchicalLoggingEnabled) {
if (_level != null) return _level;
@@ -109,8 +101,8 @@
return _rootLevel;
}
- /** Override the level for this particular [Logger] and its children. */
- void set level(Level value) {
+ /// Override the level for this particular [Logger] and its children.
+ set level(Level value) {
if (hierarchicalLoggingEnabled && parent != null) {
_level = value;
} else {
@@ -143,7 +135,7 @@
}
}
- /** Whether a message for [value]'s level is loggable in this logger. */
+ /// Whether a message for [value]'s level is loggable in this logger.
bool isLoggable(Level value) => (value >= level);
/// Adds a log record for a [message] at a particular [logLevel] if
@@ -167,23 +159,26 @@
[Object error, StackTrace stackTrace, Zone zone]) {
Object object;
if (isLoggable(logLevel)) {
- if (message is Function) message = message();
- if (message is! String) {
- object = message;
- message = message.toString();
+ if (message is Function) {
+ message = message();
}
+
+ String msg;
+ if (message is String) {
+ msg = message;
+ } else {
+ msg = message.toString();
+ object = message;
+ }
+
if (stackTrace == null && logLevel >= recordStackTraceAtLevel) {
- try {
- throw "autogenerated stack trace for $logLevel $message";
- } catch (e, t) {
- stackTrace = t;
- if (error == null) error = e;
- }
+ stackTrace = StackTrace.current;
+ error ??= 'autogenerated stack trace for $logLevel $msg';
}
if (zone == null) zone = Zone.current;
var record = new LogRecord(
- logLevel, message, fullName, error, stackTrace, zone, object);
+ logLevel, msg, fullName, error, stackTrace, zone, object);
if (hierarchicalLoggingEnabled) {
var target = this;
@@ -197,35 +192,35 @@
}
}
- /** Log message at level [Level.FINEST]. */
+ /// Log message at level [Level.FINEST].
void finest(message, [Object error, StackTrace stackTrace]) =>
log(Level.FINEST, message, error, stackTrace);
- /** Log message at level [Level.FINER]. */
+ /// Log message at level [Level.FINER].
void finer(message, [Object error, StackTrace stackTrace]) =>
log(Level.FINER, message, error, stackTrace);
- /** Log message at level [Level.FINE]. */
+ /// Log message at level [Level.FINE].
void fine(message, [Object error, StackTrace stackTrace]) =>
log(Level.FINE, message, error, stackTrace);
- /** Log message at level [Level.CONFIG]. */
+ /// Log message at level [Level.CONFIG].
void config(message, [Object error, StackTrace stackTrace]) =>
log(Level.CONFIG, message, error, stackTrace);
- /** Log message at level [Level.INFO]. */
+ /// Log message at level [Level.INFO].
void info(message, [Object error, StackTrace stackTrace]) =>
log(Level.INFO, message, error, stackTrace);
- /** Log message at level [Level.WARNING]. */
+ /// Log message at level [Level.WARNING].
void warning(message, [Object error, StackTrace stackTrace]) =>
log(Level.WARNING, message, error, stackTrace);
- /** Log message at level [Level.SEVERE]. */
+ /// Log message at level [Level.SEVERE].
void severe(message, [Object error, StackTrace stackTrace]) =>
log(Level.SEVERE, message, error, stackTrace);
- /** Log message at level [Level.SHOUT]. */
+ /// Log message at level [Level.SHOUT].
void shout(message, [Object error, StackTrace stackTrace]) =>
log(Level.SHOUT, message, error, stackTrace);
@@ -246,67 +241,63 @@
}
}
- /** Top-level root [Logger]. */
+ /// Top-level root [Logger].
static final Logger root = new Logger('');
- /** All [Logger]s in the system. */
+ /// All [Logger]s in the system.
static final Map<String, Logger> _loggers = <String, Logger>{};
}
-/** Handler callback to process log entries as they are added to a [Logger]. */
-typedef void LoggerHandler(LogRecord);
+/// Handler callback to process log entries as they are added to a [Logger].
+typedef void LoggerHandler(LogRecord record);
-/**
- * [Level]s to control logging output. Logging can be enabled to include all
- * levels above certain [Level]. [Level]s are ordered using an integer
- * value [Level.value]. The predefined [Level] constants below are sorted as
- * follows (in descending order): [Level.SHOUT], [Level.SEVERE],
- * [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER],
- * [Level.FINEST], and [Level.ALL].
- *
- * We recommend using one of the predefined logging levels. If you define your
- * own level, make sure you use a value between those used in [Level.ALL] and
- * [Level.OFF].
- */
+/// [Level]s to control logging output. Logging can be enabled to include all
+/// levels above certain [Level]. [Level]s are ordered using an integer
+/// value [Level.value]. The predefined [Level] constants below are sorted as
+/// follows (in descending order): [Level.SHOUT], [Level.SEVERE],
+/// [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER],
+/// [Level.FINEST], and [Level.ALL].
+///
+/// We recommend using one of the predefined logging levels. If you define your
+/// own level, make sure you use a value between those used in [Level.ALL] and
+/// [Level.OFF].
class Level implements Comparable<Level> {
final String name;
- /**
- * Unique value for this level. Used to order levels, so filtering can exclude
- * messages whose level is under certain value.
- */
+ /// Unique value for this level. Used to order levels, so filtering can
+ /// exclude messages whose level is under certain value.
final int value;
const Level(this.name, this.value);
- /** Special key to turn on logging for all levels ([value] = 0). */
+ /// Special key to turn on logging for all levels ([value] = 0).
static const Level ALL = const Level('ALL', 0);
- /** Special key to turn off all logging ([value] = 2000). */
+ /// Special key to turn off all logging ([value] = 2000).
static const Level OFF = const Level('OFF', 2000);
- /** Key for highly detailed tracing ([value] = 300). */
+ /// Key for highly detailed tracing ([value] = 300).
static const Level FINEST = const Level('FINEST', 300);
- /** Key for fairly detailed tracing ([value] = 400). */
+ /// Key for fairly detailed tracing ([value] = 400).
static const Level FINER = const Level('FINER', 400);
- /** Key for tracing information ([value] = 500). */
+ /// Key for tracing information ([value] = 500).
static const Level FINE = const Level('FINE', 500);
- /** Key for static configuration messages ([value] = 700). */
+ /// Key for static configuration messages ([value] = 700).
static const Level CONFIG = const Level('CONFIG', 700);
- /** Key for informational messages ([value] = 800). */
+ /// Key for informational messages ([value] = 800).
static const Level INFO = const Level('INFO', 800);
- /** Key for potential problems ([value] = 900). */
+ /// Key for potential problems ([value] = 900).
static const Level WARNING = const Level('WARNING', 900);
- /** Key for serious failures ([value] = 1000). */
+ /// Key for serious failures ([value] = 1000).
static const Level SEVERE = const Level('SEVERE', 1000);
- /** Key for extra debugging loudness ([value] = 1200). */
+ /// Key for extra debugging loudness ([value] = 1200).
static const Level SHOUT = const Level('SHOUT', 1200);
static const List<Level> LEVELS = const [
@@ -322,45 +313,50 @@
OFF
];
- bool operator ==(other) => other is Level && value == other.value;
+ @override
+ bool operator ==(Object other) => other is Level && value == other.value;
bool operator <(Level other) => value < other.value;
bool operator <=(Level other) => value <= other.value;
bool operator >(Level other) => value > other.value;
bool operator >=(Level other) => value >= other.value;
+
+ @override
int compareTo(Level other) => value - other.value;
+
+ @override
int get hashCode => value;
+
+ @override
String toString() => name;
}
-/**
- * A log entry representation used to propagate information from [Logger] to
- * individual [Handler]s.
- */
+/// A log entry representation used to propagate information from [Logger] to
+/// individual handlers.
class LogRecord {
final Level level;
final String message;
- /** Non-string message passed to Logger. */
+ /// Non-string message passed to Logger.
final Object object;
- /** Logger where this record is stored. */
+ /// Logger where this record is stored.
final String loggerName;
- /** Time when this record was created. */
+ /// Time when this record was created.
final DateTime time;
- /** Unique sequence number greater than all log records created before it. */
+ /// Unique sequence number greater than all log records created before it.
final int sequenceNumber;
static int _nextNumber = 0;
- /** Associated error (if any) when recording errors messages. */
+ /// Associated error (if any) when recording errors messages.
final Object error;
- /** Associated stackTrace (if any) when recording errors messages. */
+ /// Associated stackTrace (if any) when recording errors messages.
final StackTrace stackTrace;
- /** Zone of the calling code which resulted in this LogRecord. */
+ /// Zone of the calling code which resulted in this LogRecord.
final Zone zone;
LogRecord(this.level, this.message, this.loggerName,
@@ -368,5 +364,6 @@
: time = new DateTime.now(),
sequenceNumber = LogRecord._nextNumber++;
+ @override
String toString() => '[${level.name}] $loggerName: $message';
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 97eec7a..3dc8424 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: logging
-version: 0.11.3+1
+version: 0.11.4-dev
author: Dart Team <misc@dartlang.org>
description: >
Provides APIs for debugging and error logging. This library introduces
diff --git a/test/logging_test.dart b/test/logging_test.dart
index b73fdcc..c854344 100644
--- a/test/logging_test.dart
+++ b/test/logging_test.dart
@@ -191,7 +191,7 @@
test('custom zone', () {
var root = Logger.root;
- var recordingZone;
+ Zone recordingZone;
var records = new List<LogRecord>();
root.onRecord.listen(records.add);
@@ -207,23 +207,23 @@
});
group('detached loggers', () {
- test("create new instances of Logger", () {
- Logger a1 = new Logger.detached("a");
- Logger a2 = new Logger.detached("a");
- Logger a = new Logger("a");
+ test('create new instances of Logger', () {
+ Logger a1 = new Logger.detached('a');
+ Logger a2 = new Logger.detached('a');
+ Logger a = new Logger('a');
expect(a1, isNot(a2));
expect(a1, isNot(a));
expect(a2, isNot(a));
});
- test("parent is null", () {
- Logger a = new Logger.detached("a");
+ test('parent is null', () {
+ Logger a = new Logger.detached('a');
expect(a.parent, null);
});
- test("children is empty", () {
- Logger a = new Logger.detached("a");
+ test('children is empty', () {
+ Logger a = new Logger.detached('a');
expect(a.children, {});
});
});
@@ -304,27 +304,29 @@
test('add/remove handlers - no hierarchy', () {
int calls = 0;
- var handler = (_) {
+ void handler(_) {
calls++;
- };
+ }
+
final sub = c.onRecord.listen(handler);
- root.info("foo");
- root.info("foo");
+ root.info('foo');
+ root.info('foo');
expect(calls, equals(2));
sub.cancel();
- root.info("foo");
+ root.info('foo');
expect(calls, equals(2));
});
test('add/remove handlers - with hierarchy', () {
hierarchicalLoggingEnabled = true;
int calls = 0;
- var handler = (_) {
+ void handler(_) {
calls++;
- };
+ }
+
c.onRecord.listen(handler);
- root.info("foo");
- root.info("foo");
+ root.info('foo');
+ root.info('foo');
expect(calls, equals(0));
});
@@ -529,13 +531,18 @@
});
var callCount = 0;
- var myClosure = () => "${++callCount}";
+ var myClosure = () => '${++callCount}';
root.info(myClosure);
root.finer(myClosure); // Should not get evaluated.
root.warning(myClosure);
- expect(messages, equals(['INFO: 1', 'WARNING: 2',]));
+ expect(
+ messages,
+ equals([
+ 'INFO: 1',
+ 'WARNING: 2',
+ ]));
});
test('message logging - calls toString', () {
@@ -607,12 +614,7 @@
});
test('provided trace is used if given', () {
- var trace;
- try {
- throw 'trace';
- } catch (e, t) {
- trace = t;
- }
+ var trace = StackTrace.current;
var records = new List<LogRecord>();
recordStackTraceAtLevel = Level.WARNING;
root.onRecord.listen(records.add);