Allow private types in pretty print (#116)

Closes #115

The default print of `"?"` for private implementation classes can be
confusing, especially cases like `[Uri.parse('')]` which pretty prints
as `[?:]`.

- Add more types to print like "primitives" where they already include
  the type name in their default `toString`.
- Remove handling of `null`, it is handled already in the calling
  function.
- Add handling for some core types that are backed by private
  implementation classes.
- Remove the unnecessary try/catch and outdated comments.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3ce053..12e0105 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 - Update minimum Dart SDK to `2.2.0`.
 - Consistently point to `isA` as a replacement for `instanceOf`.
+- Pretty print with private type names.
 
 ## 0.12.5
 
diff --git a/lib/src/pretty_print.dart b/lib/src/pretty_print.dart
index 9fe8882..5986d32 100644
--- a/lib/src/pretty_print.dart
+++ b/lib/src/pretty_print.dart
@@ -104,6 +104,9 @@
       if (object is num ||
           object is bool ||
           object is Function ||
+          object is RegExp ||
+          object is MapEntry ||
+          object is Expando ||
           object == null ||
           defaultToString) {
         return value;
@@ -118,21 +121,14 @@
 
 String _indent(int length) => List.filled(length, ' ').join('');
 
-/// Returns the name of the type of [x], or "Unknown" if the type name can't be
-/// determined.
+/// Returns the name of the type of [x] with fallbacks for core types with
+/// private implementations.
 String _typeName(x) {
-  // dart2js blows up on some objects (e.g. window.navigator).
-  // So we play safe here.
-  try {
-    if (x == null) return "null";
-    if (x is Type) return "Type";
-    var type = x.runtimeType.toString();
-    // TODO(nweiz): if the object's type is private, find a public superclass to
-    // display once there's a portable API to do that.
-    return type.startsWith("_") ? "?" : type;
-  } catch (e) {
-    return "?";
-  }
+  if (x is Type) return "Type";
+  if (x is Uri) return "Uri";
+  if (x is Set) return "Set";
+  if (x is BigInt) return "BigInt";
+  return '${x.runtimeType}';
 }
 
 /// Returns [source] with any control characters replaced by their escape
diff --git a/test/pretty_print_test.dart b/test/pretty_print_test.dart
index 2cab1ef..90954de 100644
--- a/test/pretty_print_test.dart
+++ b/test/pretty_print_test.dart
@@ -242,7 +242,8 @@
     });
 
     test('with a custom [toString] and a private name', () {
-      expect(prettyPrint(_PrivateName()), equals('?:<string representation>'));
+      expect(prettyPrint(_PrivateName()),
+          equals('_PrivateName:<string representation>'));
     });
   });
 
@@ -256,7 +257,8 @@
     });
 
     test("that's not a list and has a private name", () {
-      expect(prettyPrint(_PrivateNameIterable()), equals("?:[1, 2, 3]"));
+      expect(prettyPrint(_PrivateNameIterable()),
+          equals("_PrivateNameIterable:[1, 2, 3]"));
     });
   });