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);