[pigeon] made nested classes that aren't referenced in the apis work (#169)

diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index c83d80a..1df17cc 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.1.1
+
+* Fixed issue where nested types didn't work if they weren't present in the Api.
+
 ## 0.1.0
 
 * Added pigeon.dart.
diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart
index f67ab73..0a9a7cc 100644
--- a/packages/pigeon/lib/ast.dart
+++ b/packages/pigeon/lib/ast.dart
@@ -57,6 +57,11 @@
 
   /// The data-type of the field (ex 'String' or 'int').
   String dataType;
+
+  @override
+  String toString() {
+    return '(Field name:$name)';
+  }
 }
 
 /// Represents a class with [Field]s.
@@ -69,6 +74,11 @@
 
   /// All the fields contained in the class.
   List<Field> fields;
+
+  @override
+  String toString() {
+    return '(Class name:$name fields:$fields)';
+  }
 }
 
 /// Top-level node for the AST.
@@ -81,4 +91,9 @@
 
   /// All the API's contained in the AST.
   List<Api> apis;
+
+  @override
+  String toString() {
+    return '(Root classes:$classes apis:$apis)';
+  }
 }
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index 5df2840..18c8590 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -128,7 +128,8 @@
           : field.dataType;
       return HostDatatype(datatype: customName, isBuiltin: false);
     } else {
-      return null;
+      throw Exception(
+          'unrecognized datatype for field:"${field.name}" of type:"${field.dataType}"');
     }
   } else {
     return HostDatatype(datatype: datatype, isBuiltin: true);
diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart
index f91828d..6207757 100644
--- a/packages/pigeon/lib/pigeon_lib.dart
+++ b/packages/pigeon/lib/pigeon_lib.dart
@@ -74,6 +74,11 @@
 
   /// What line the error happened on.
   int lineNumber;
+
+  @override
+  String toString() {
+    return '(Error message:"$message" filename:"$filename" lineNumber:$lineNumber)';
+  }
 }
 
 bool _isApi(ClassMirror classMirror) {
@@ -157,6 +162,32 @@
     return klass;
   }
 
+  Iterable<Class> _parseClassMirrors(Iterable<ClassMirror> mirrors) sync* {
+    for (ClassMirror mirror in mirrors) {
+      yield _parseClassMirror(mirror);
+      final Iterable<ClassMirror> nestedTypes = mirror.declarations.values
+          .whereType<VariableMirror>()
+          .map((VariableMirror variable) => variable.type)
+          .whereType<ClassMirror>()
+
+          ///note: This will need to be changed if we support generic types.
+          .where((ClassMirror mirror) =>
+              !_validTypes.contains(MirrorSystem.getName(mirror.simpleName)));
+      for (Class klass in _parseClassMirrors(nestedTypes)) {
+        yield klass;
+      }
+    }
+  }
+
+  Iterable<T> _unique<T, U>(Iterable<T> iter, U Function(T val) getKey) sync* {
+    final Set<U> seen = <U>{};
+    for (T val in iter) {
+      if (seen.add(getKey(val))) {
+        yield val;
+      }
+    }
+  }
+
   /// Use reflection to parse the [types] provided.
   ParseResults parse(List<Type> types) {
     final Root root = Root();
@@ -185,7 +216,8 @@
       }
     }
 
-    root.classes = classes.map(_parseClassMirror).toList();
+    root.classes =
+        _unique(_parseClassMirrors(classes), (Class x) => x.name).toList();
 
     root.apis = <Api>[];
     for (ClassMirror apiMirror in apis) {
diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml
index b10abb9..537ac2f 100644
--- a/packages/pigeon/pubspec.yaml
+++ b/packages/pigeon/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pigeon
-version: 0.1.0
+version: 0.1.1
 description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
 homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
 dependencies:
diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart
index 6772a4e..2d3b449 100644
--- a/packages/pigeon/test/pigeon_lib_test.dart
+++ b/packages/pigeon/test/pigeon_lib_test.dart
@@ -53,6 +53,19 @@
   Output1 doit();
 }
 
+class OnlyVisibleFromNesting {
+  String foo;
+}
+
+class Nestor {
+  OnlyVisibleFromNesting nested;
+}
+
+@HostApi()
+abstract class NestorApi {
+  Nestor getit();
+}
+
 void main() {
   test('parse args - input', () {
     final PigeonOptions opts =
@@ -190,4 +203,16 @@
     expect(results.root.apis[0].dartHostTestHandler,
         equals('ApiWithMockDartClassMock'));
   });
+
+  test('only visible from nesting', () {
+    final Pigeon dartle = Pigeon.setup();
+    final ParseResults results = dartle.parse(<Type>[NestorApi]);
+    expect(results.errors.length, 0);
+    expect(results.root.apis.length, 1);
+    final List<String> classNames =
+        results.root.classes.map((Class x) => x.name).toList();
+    expect(classNames.length, 2);
+    expect(classNames.contains('Nestor'), true);
+    expect(classNames.contains('OnlyVisibleFromNesting'), true);
+  });
 }