Move well-known-type support code to mixins. (#264)

* Move well-known-type support code to mixins.

This makes it easier to implement support for additional well-known types
as it moves more code away from being injected strings.

The static methods still have to be injected, because you cannot mix in
static methods.

Changes mixin imports in generated code to use a prefix instead of a name.

Also changes the import of dart:core to not use a `show` list. It was
not needed after we use prefix imports.

Also moves the protobuf/lib/src/mixins_meta.dart and associated tests to
protoc_plugin/lib/mixins.dart. It was not used there.
diff --git a/protobuf/lib/src/protobuf/mixins/well_known.dart b/protobuf/lib/src/protobuf/mixins/well_known.dart
new file mode 100644
index 0000000..6f8c647
--- /dev/null
+++ b/protobuf/lib/src/protobuf/mixins/well_known.dart
@@ -0,0 +1,68 @@
+import 'package:fixnum/fixnum.dart';
+
+import '../../../protobuf.dart';
+
+abstract class AnyMixin {
+  String get typeUrl;
+  set typeUrl(String value);
+  List<int> get value;
+  set value(List<int> value);
+
+  /// Returns `true` if the encoded message matches the type of [instance].
+  ///
+  /// Can be used with a default instance:
+  /// `any.canUnpackInto(Message.getDefault())`
+  bool canUnpackInto(GeneratedMessage instance) {
+    return canUnpackIntoHelper(instance, typeUrl);
+  }
+
+  /// Unpacks the message in [value] into [instance].
+  ///
+  /// Throws a [InvalidProtocolBufferException] if [typeUrl] does not correspond
+  /// to the type of [instance].
+  ///
+  /// A typical usage would be `any.unpackInto(Message())`.
+  ///
+  /// Returns [instance].
+  T unpackInto<T extends GeneratedMessage>(T instance,
+      {ExtensionRegistry extensionRegistry = ExtensionRegistry.EMPTY}) {
+    unpackIntoHelper(value, instance, typeUrl,
+        extensionRegistry: extensionRegistry);
+    return instance;
+  }
+
+  /// Updates [target] to be the packed representation of [message].
+  ///
+  /// The [typeUrl] will be [typeUrlPrefix]/`fullName` where `fullName` is
+  /// the fully qualified name of the type of [message].
+  static void packIntoAny(AnyMixin target, GeneratedMessage message,
+      {String typeUrlPrefix = 'type.googleapis.com'}) {
+    target.value = message.writeToBuffer();
+    target.typeUrl = '${typeUrlPrefix}/${message.info_.qualifiedMessageName}';
+  }
+}
+
+abstract class TimestampMixin {
+  Int64 get seconds;
+  set seconds(Int64 value);
+
+  int get nanos;
+  set nanos(int value);
+
+  /// Converts an instance to [DateTime].
+  ///
+  /// The result is in UTC time zone and has microsecond precision, as
+  /// [DateTime] does not support nanosecond precision.
+  DateTime toDateTime() => new DateTime.fromMicrosecondsSinceEpoch(
+      seconds.toInt() * Duration.microsecondsPerSecond + nanos ~/ 1000,
+      isUtc: true);
+
+  /// Updates [target] to be the time at [datetime].
+  ///
+  /// Time zone information will not be preserved.
+  static void setFromDateTime(TimestampMixin target, DateTime dateTime) {
+    int micros = dateTime.microsecondsSinceEpoch;
+    target.seconds = Int64(micros ~/ Duration.microsecondsPerSecond);
+    target.nanos = (micros % Duration.microsecondsPerSecond).toInt() * 1000;
+  }
+}
diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index a99c0db..b960658 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,6 +1,7 @@
 ## 18.0.0
 
 * Breaking: Generates code that requires at least `protobuf` 0.14.0.
+
 * Generate the non-camel-case name of fields when it cannot be derived from the json name.
 
 * Breaking: Use the correct proto3 Json CamelCase names for the string representation of field
@@ -20,6 +21,9 @@
   `GeneratedMessage.toString()` also uses the string representation. It will now print the
   json-name.
 
+* Well-known types (for now only `google.protobuf.Any` and `google.protobuf.Timestamp`) now uses a
+  mixin to add special handling code instead of hardcoding it in the compiler.
+
 ## 17.0.5
 
 * Remove unnecessary cast from generated grpc stubs. 
diff --git a/protoc_plugin/lib/file_generator.dart b/protoc_plugin/lib/file_generator.dart
index 8ce17a1..c1b355c 100644
--- a/protoc_plugin/lib/file_generator.dart
+++ b/protoc_plugin/lib/file_generator.dart
@@ -6,15 +6,16 @@
 
 final _dartIdentifier = RegExp(r'^\w+$');
 final _formatter = DartFormatter();
-final String _protobufImportPrefix = r'$pb';
-final String _asyncImportPrefix = r'$async';
+const String _protobufImportPrefix = r'$pb';
+const String _asyncImportPrefix = r'$async';
 const String _coreImportPrefix = r'$core';
-final String _grpcImportPrefix = r'$grpc';
-final String _protobufImport =
+const String _grpcImportPrefix = r'$grpc';
+const String _mixinImportPrefix = r'$mixin';
+const String _protobufImport =
     "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;";
-final String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
-final String _coreImport = "import 'dart:core' as $_coreImportPrefix";
-final String _grpcImport =
+const String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
+const String _coreImport = "import 'dart:core' as $_coreImportPrefix;";
+const String _grpcImport =
     "import 'package:grpc/service_api.dart' as $_grpcImportPrefix;";
 
 /// Generates the Dart output files for one .proto input file.
@@ -285,8 +286,7 @@
       out.println(_asyncImport);
     }
 
-    out.println('$_coreImport show '
-        'bool, Deprecated, double, int, List, Map, override, pragma, String;');
+    out.println(_coreImport);
     out.println();
 
     if (_needsFixnumImport) {
@@ -298,12 +298,9 @@
       out.println();
     }
 
-    var mixinImports = findMixinsToImport();
-    var importNames = mixinImports.keys.toList();
-    importNames.sort();
-    for (var imp in importNames) {
-      var symbols = mixinImports[imp];
-      out.println("import '${imp}' show ${symbols.join(', ')};");
+    final mixinImports = findMixinImports();
+    for (var libraryUri in mixinImports) {
+      out.println("import '$libraryUri' as $_mixinImportPrefix;");
     }
     if (mixinImports.isNotEmpty) out.println();
 
@@ -322,8 +319,6 @@
     }
     if (enumImports.isNotEmpty) out.println();
 
-    _writeWellKnownImports(out);
-
     // Export enums in main file for backward compatibility.
     if (enumCount > 0) {
       Uri resolvedImport =
@@ -333,17 +328,6 @@
     }
   }
 
-  void _writeWellKnownImports(IndentingWriter out) {
-    for (final message in messageGenerators) {
-      final importStatements =
-          wellKnownTypeForFullName(message.fullName)?.extraImports ??
-              <String>[];
-      for (String importStatement in importStatements) {
-        out.println(importStatement);
-      }
-    }
-  }
-
   bool get _needsFixnumImport {
     for (var m in messageGenerators) {
       if (m.needsFixnumImport) return true;
@@ -376,29 +360,18 @@
     imports.remove(this);
   }
 
-  /// Returns a map from import names to the Dart symbols to be imported.
-  Map<String, List<String>> findMixinsToImport() {
+  /// Returns a sorted list of imports needed to support all mixins.
+  List<String> findMixinImports() {
     var mixins = Set<PbMixin>();
     for (MessageGenerator m in messageGenerators) {
       m.addMixinsTo(mixins);
     }
 
-    var imports = <String, List<String>>{};
-    for (var m in mixins) {
-      var imp = m.importFrom;
-      List<String> symbols = imports[imp];
-      if (symbols == null) {
-        symbols = [];
-        imports[imp] = symbols;
-      }
-      symbols.add(m.name);
-    }
-
-    for (var imp in imports.keys) {
-      imports[imp].sort();
-    }
-
-    return imports;
+    return mixins
+        .map((mixin) => mixin.importFrom)
+        .toSet()
+        .toList(growable: false)
+          ..sort();
   }
 
   /// Returns the contents of the .pbenum.dart file for this .proto file.
@@ -413,7 +386,7 @@
       // Make sure any other symbols in dart:core don't cause name conflicts
       // with enums that have the same name.
       out.println("// ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME");
-      out.println("$_coreImport show int, dynamic, String, List, Map;");
+      out.println(_coreImport);
       out.println(_protobufImport);
       out.println();
     }
@@ -450,7 +423,7 @@
       out.println();
       out.println(_protobufImport);
       out.println();
-      out.println("$_coreImport show String, Map, ArgumentError, dynamic;");
+      out.println(_coreImport);
     }
 
     // Import .pb.dart files needed for requests and responses.
@@ -489,7 +462,7 @@
 
     out.println(_asyncImport);
     out.println();
-    out.println("$_coreImport show int, String, List;\n");
+    out.println(_coreImport);
     out.println();
     out.println(_grpcImport);
 
diff --git a/protoc_plugin/lib/message_generator.dart b/protoc_plugin/lib/message_generator.dart
index 4eedd5f..e09566b 100644
--- a/protoc_plugin/lib/message_generator.dart
+++ b/protoc_plugin/lib/message_generator.dart
@@ -22,25 +22,6 @@
 }
 
 class MessageGenerator extends ProtobufContainer {
-  /// Returns the mixin for this message, or null if none.
-  ///
-  /// First searches [declaredMixins], then internal mixins declared by
-  /// [findMixin].
-  static PbMixin _getMixin(DescriptorProto desc, FileDescriptorProto file,
-      Map<String, PbMixin> declaredMixins, PbMixin defaultMixin) {
-    if (!desc.hasOptions() || !desc.options.hasExtension(Dart_options.mixin)) {
-      return defaultMixin;
-    }
-
-    String name = desc.options.getExtension(Dart_options.mixin);
-    if (name.isEmpty) return null; // don't use any mixins (override default)
-    var mixin = declaredMixins[name] ?? findMixin(name);
-    if (mixin == null) {
-      throw '${desc.name} in ${file.name}: mixin "$name" not found';
-    }
-    return mixin;
-  }
-
   /// The name of the Dart class to generate.
   final String classname;
 
@@ -66,7 +47,7 @@
   String get messageName =>
       fullName.substring(package.isEmpty ? 0 : package.length + 1);
 
-  final PbMixin mixin;
+  PbMixin mixin;
 
   final ProtobufContainer _parent;
   final DescriptorProto _descriptor;
@@ -107,10 +88,9 @@
         fullName = parent.fullName == ''
             ? descriptor.name
             : '${parent.fullName}.${descriptor.name}',
-        mixin = _getMixin(descriptor, parent.fileGen.descriptor, declaredMixins,
-            defaultMixin),
         _oneofFields =
             List.generate(descriptor.oneofDecl.length, (int index) => []) {
+    mixin = _getMixin(declaredMixins, defaultMixin);
     for (var i = 0; i < _descriptor.enumType.length; i++) {
       EnumDescriptorProto e = _descriptor.enumType[i];
       _enumGenerators.add(EnumGenerator.nested(e, this, _usedTopLevelNames, i));
@@ -303,7 +283,8 @@
 
     var mixinClause = '';
     if (mixin != null) {
-      var mixinNames = mixin.findMixinsToApply().map((m) => m.name);
+      var mixinNames =
+          mixin.findMixinsToApply().map((m) => '$_mixinImportPrefix.${m.name}');
       mixinClause = ' with ${mixinNames.join(", ")}';
     }
 
@@ -387,7 +368,7 @@
           'static ${classname} getDefault() => _defaultInstance ??= create()..freeze();');
       out.println('static ${classname} _defaultInstance;');
       generateFieldsAccessorsMutators(out);
-      wellKnownTypeForFullName(fullName)?.generateMethods(out);
+      mixin?.injectHelpers(out);
     });
     out.println();
   }
@@ -621,4 +602,25 @@
       e.generateConstants(out);
     }
   }
+
+  /// Returns the mixin for this message, or null if none.
+  ///
+  /// First searches [wellKnownMixins], then [declaredMixins],
+  /// then internal mixins declared by [findMixin].
+  PbMixin _getMixin(Map<String, PbMixin> declaredMixins, PbMixin defaultMixin) {
+    PbMixin wellKnownMixin = wellKnownMixinForFullName(fullName);
+    if (wellKnownMixin != null) return wellKnownMixin;
+    if (!_descriptor.hasOptions() ||
+        !_descriptor.options.hasExtension(Dart_options.mixin)) {
+      return defaultMixin;
+    }
+
+    String name = _descriptor.options.getExtension(Dart_options.mixin);
+    if (name.isEmpty) return null; // don't use any mixins (override default)
+    var mixin = declaredMixins[name] ?? findMixin(name);
+    if (mixin == null) {
+      throw '${_descriptor.name} in ${_parent.fileGen.descriptor.name}: mixin "$name" not found';
+    }
+    return mixin;
+  }
 }
diff --git a/protobuf/lib/mixins_meta.dart b/protoc_plugin/lib/mixins.dart
similarity index 78%
rename from protobuf/lib/mixins_meta.dart
rename to protoc_plugin/lib/mixins.dart
index cfef320..06b9dc6 100644
--- a/protobuf/lib/mixins_meta.dart
+++ b/protoc_plugin/lib/mixins.dart
@@ -4,16 +4,15 @@
 
 /// Provides metadata about mixins to dart-protoc-plugin.
 /// (Experimental API; subject to change.)
-library protobuf.mixins.meta;
+import 'indenting_writer.dart';
 
-/// Entry point called by dart-protoc-plugin.
+/// Finds [name] in the exported mixins.
 PbMixin findMixin(String name) {
-  for (var m in _exportedMixins) {
-    if (m.name == name) {
-      return m;
-    }
-  }
-  return null; // not found
+  const _exportedMixins = {
+    'PbMapMixin': _pbMapMixin,
+    'PbEventMixin': _pbEventMixin,
+  };
+  return _exportedMixins[name];
 }
 
 /// PbMixin contains metadata needed by dart-protoc-plugin to apply a mixin.
@@ -35,7 +34,13 @@
   /// May be null if the mixin doesn't reserve any new names.
   final List<String> reservedNames;
 
-  const PbMixin(this.name, {this.importFrom, this.parent, this.reservedNames});
+  ///  Code to inject into the class using the mixin.
+  ///
+  /// Typically used for static helpers since you cannot mix in static members.
+  final List<String> injectedHelpers;
+
+  const PbMixin(this.name,
+      {this.importFrom, this.parent, this.reservedNames, this.injectedHelpers});
 
   /// Returns the mixin and its ancestors, in the order they should be applied.
   Iterable<PbMixin> findMixinsToApply() {
@@ -57,10 +62,13 @@
     }
     return names;
   }
-}
 
-/// The mixins that findMixin() can return.
-final _exportedMixins = [_pbMapMixin, _pbEventMixin];
+  void injectHelpers(IndentingWriter out) {
+    if (injectedHelpers != null && injectedHelpers.isNotEmpty) {
+      out.println(injectedHelpers.join('\n'));
+    }
+  }
+}
 
 const _pbMapMixin = PbMixin("PbMapMixin",
     importFrom: "package:protobuf/src/protobuf/mixins/map_mixin.dart",
diff --git a/protoc_plugin/lib/protoc.dart b/protoc_plugin/lib/protoc.dart
index b354cec..67f35f4 100644
--- a/protoc_plugin/lib/protoc.dart
+++ b/protoc_plugin/lib/protoc.dart
@@ -4,7 +4,6 @@
 import 'dart:io';
 
 import 'package:dart_style/dart_style.dart';
-import 'package:protobuf/mixins_meta.dart';
 import 'package:protobuf/protobuf.dart';
 import 'package:path/path.dart' as path;
 
@@ -15,6 +14,7 @@
 import 'const_generator.dart' show writeJsonConst;
 import 'indenting_writer.dart';
 import 'names.dart';
+import 'mixins.dart';
 
 part 'base_type.dart';
 part 'client_generator.dart';
diff --git a/protoc_plugin/lib/well_known_types.dart b/protoc_plugin/lib/well_known_types.dart
index a403c3e..9ac1829 100644
--- a/protoc_plugin/lib/well_known_types.dart
+++ b/protoc_plugin/lib/well_known_types.dart
@@ -4,91 +4,37 @@
 
 part of protoc;
 
-abstract class WellKnownType {
-  const WellKnownType();
+PbMixin wellKnownMixinForFullName(String qualifiedName) =>
+    _wellKnownMixins[qualifiedName];
 
-  List<String> get extraImports => <String>[];
-
-  void generateMethods(IndentingWriter out);
-}
-
-class _Any extends WellKnownType {
-  const _Any();
-
-  /// Generates methods for the Any message class for packing and unpacking
-  /// values.
-  @override
-  void generateMethods(IndentingWriter out) {
-    out.println('''
-  /// Unpacks the message in [value] into [instance].
-  ///
-  /// Throws a [InvalidProtocolBufferException] if [typeUrl] does not correspond
-  /// to the type of [instance].
-  ///
-  /// A typical usage would be `any.unpackInto(Message())`.
-  ///
-  /// Returns [instance].
-  T unpackInto<T extends $_protobufImportPrefix.GeneratedMessage>(T instance,
-      {$_protobufImportPrefix.ExtensionRegistry extensionRegistry = $_protobufImportPrefix.ExtensionRegistry.EMPTY}) {
-    $_protobufImportPrefix.unpackIntoHelper(value, instance, typeUrl,
-        extensionRegistry: extensionRegistry);
-    return instance;
-  }
-
-  /// Returns `true` if the encoded message matches the type of [instance].
-  ///
-  /// Can be used with a default instance:
-  /// `any.canUnpackInto(Message.getDefault())`
-  $_coreImportPrefix.bool canUnpackInto($_protobufImportPrefix.GeneratedMessage instance) {
-    return $_protobufImportPrefix.canUnpackIntoHelper(instance, typeUrl);
-  }
-
-  /// Creates a new [Any] encoding [message].
-  ///
-  /// The [typeUrl] will be [typeUrlPrefix]/`fullName` where `fullName` is
-  /// the fully qualified name of the type of [message].
-  static Any pack($_protobufImportPrefix.GeneratedMessage message,
-      {$_coreImportPrefix.String typeUrlPrefix = 'type.googleapis.com'}) {
-    return Any()
-      ..value = message.writeToBuffer()
-      ..typeUrl = '\${typeUrlPrefix}/\${message.info_.qualifiedMessageName}';
-  }''');
-  }
-}
-
-class _Timestamp extends WellKnownType {
-  const _Timestamp();
-
-  List<String> get extraImports =>
-      [r"import 'dart:core' as $core show DateTime, Duration;"];
-
-  @override
-  void generateMethods(IndentingWriter out) {
-    out.println('''
-  /// Converts an instance to [DateTime].
-  ///
-  /// The result is in UTC time zone and has microsecond precision, as
-  /// [DateTime] does not support nanosecond precision.
-  $_coreImportPrefix.DateTime toDateTime() => $_coreImportPrefix.DateTime.fromMicrosecondsSinceEpoch(
-      seconds.toInt() * $_coreImportPrefix.Duration.microsecondsPerSecond + nanos ~/ 1000,
-      isUtc: true);
-
-  /// Creates a new instance from [dateTime].
-  ///
-  /// Time zone information will not be preserved.
-  static Timestamp fromDateTime($_coreImportPrefix.DateTime dateTime) {
-    $_coreImportPrefix.int micros = dateTime.microsecondsSinceEpoch;
-    return Timestamp()
-      ..seconds = Int64(micros ~/ $_coreImportPrefix.Duration.microsecondsPerSecond)
-      ..nanos = (micros % $_coreImportPrefix.Duration.microsecondsPerSecond).toInt() * 1000;
-  }''');
-  }
-}
-
-const _wellKnownTypes = {
-  'google.protobuf.Any': _Any(),
-  'google.protobuf.Timestamp': _Timestamp(),
+const _wellKnownMixins = {
+  'google.protobuf.Any': PbMixin('AnyMixin',
+      importFrom: 'package:protobuf/src/protobuf/mixins/well_known.dart',
+      injectedHelpers: [
+        '''
+/// Creates a new [Any] encoding [message].
+///
+/// The [typeUrl] will be [typeUrlPrefix]/`fullName` where `fullName` is
+/// the fully qualified name of the type of [message].
+static Any pack($_protobufImportPrefix.GeneratedMessage message,
+{$_coreImportPrefix.String typeUrlPrefix = 'type.googleapis.com'}) {
+  final result = create();
+  $_mixinImportPrefix.AnyMixin.packIntoAny(result, message,
+      typeUrlPrefix: typeUrlPrefix);
+  return result;
+}'''
+      ]),
+  'google.protobuf.Timestamp': PbMixin('TimestampMixin',
+      importFrom: 'package:protobuf/src/protobuf/mixins/well_known.dart',
+      injectedHelpers: [
+        '''
+/// Creates a new instance from [dateTime].
+///
+/// Time zone information will not be preserved.
+static Timestamp fromDateTime($_coreImportPrefix.DateTime dateTime) {
+  final result = create();
+  $_mixinImportPrefix.TimestampMixin.setFromDateTime(result, dateTime);
+  return result;
+}'''
+      ]),
 };
-
-WellKnownType wellKnownTypeForFullName(String fullName) =>
-    _wellKnownTypes[fullName];
diff --git a/protoc_plugin/test/goldens/grpc_service.pb b/protoc_plugin/test/goldens/grpc_service.pb
index 1976eb5..9954f5a 100644
--- a/protoc_plugin/test/goldens/grpc_service.pb
+++ b/protoc_plugin/test/goldens/grpc_service.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
diff --git a/protoc_plugin/test/goldens/grpc_service.pbgrpc b/protoc_plugin/test/goldens/grpc_service.pbgrpc
index c4bcc35..df64211 100644
--- a/protoc_plugin/test/goldens/grpc_service.pbgrpc
+++ b/protoc_plugin/test/goldens/grpc_service.pbgrpc
@@ -7,7 +7,7 @@
 
 import 'dart:async' as $async;
 
-import 'dart:core' as $core show int, String, List;
+import 'dart:core' as $core;
 
 import 'package:grpc/service_api.dart' as $grpc;
 import 'test.pb.dart' as $0;
diff --git a/protoc_plugin/test/goldens/header_in_package.pb b/protoc_plugin/test/goldens/header_in_package.pb
index 9360866..798978a 100644
--- a/protoc_plugin/test/goldens/header_in_package.pb
+++ b/protoc_plugin/test/goldens/header_in_package.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
diff --git a/protoc_plugin/test/goldens/header_with_fixnum.pb b/protoc_plugin/test/goldens/header_with_fixnum.pb
index b7aceb3..eb98d65 100644
--- a/protoc_plugin/test/goldens/header_with_fixnum.pb
+++ b/protoc_plugin/test/goldens/header_with_fixnum.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:fixnum/fixnum.dart';
 import 'package:protobuf/protobuf.dart' as $pb;
diff --git a/protoc_plugin/test/goldens/imports.pb b/protoc_plugin/test/goldens/imports.pb
index 69888cf..27b8265 100644
--- a/protoc_plugin/test/goldens/imports.pb
+++ b/protoc_plugin/test/goldens/imports.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
diff --git a/protoc_plugin/test/goldens/oneMessage.pb b/protoc_plugin/test/goldens/oneMessage.pb
index e728680..fe417ad 100644
--- a/protoc_plugin/test/goldens/oneMessage.pb
+++ b/protoc_plugin/test/goldens/oneMessage.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
diff --git a/protoc_plugin/test/goldens/oneMessage.pb.meta b/protoc_plugin/test/goldens/oneMessage.pb.meta
index f9986a6..daba01c 100644
--- a/protoc_plugin/test/goldens/oneMessage.pb.meta
+++ b/protoc_plugin/test/goldens/oneMessage.pb.meta
@@ -2,15 +2,15 @@
   path: 4
   path: 0
   sourceFile: test
-  begin: 371
-  end: 382
+  begin: 299
+  end: 310
 }
 annotation: {
   path: 4
   path: 0
   sourceFile: test
-  begin: 636
-  end: 647
+  begin: 564
+  end: 575
 }
 annotation: {
   path: 4
@@ -18,8 +18,8 @@
   path: 2
   path: 0
   sourceFile: test
-  begin: 1564
-  end: 1570
+  begin: 1492
+  end: 1498
 }
 annotation: {
   path: 4
@@ -27,8 +27,8 @@
   path: 2
   path: 0
   sourceFile: test
-  begin: 1595
-  end: 1601
+  begin: 1523
+  end: 1529
 }
 annotation: {
   path: 4
@@ -36,8 +36,8 @@
   path: 2
   path: 0
   sourceFile: test
-  begin: 1654
-  end: 1663
+  begin: 1582
+  end: 1591
 }
 annotation: {
   path: 4
@@ -45,8 +45,8 @@
   path: 2
   path: 0
   sourceFile: test
-  begin: 1686
-  end: 1697
+  begin: 1614
+  end: 1625
 }
 annotation: {
   path: 4
@@ -54,8 +54,8 @@
   path: 2
   path: 1
   sourceFile: test
-  begin: 1735
-  end: 1739
+  begin: 1663
+  end: 1667
 }
 annotation: {
   path: 4
@@ -63,8 +63,8 @@
   path: 2
   path: 1
   sourceFile: test
-  begin: 1762
-  end: 1766
+  begin: 1690
+  end: 1694
 }
 annotation: {
   path: 4
@@ -72,8 +72,8 @@
   path: 2
   path: 1
   sourceFile: test
-  begin: 1821
-  end: 1828
+  begin: 1749
+  end: 1756
 }
 annotation: {
   path: 4
@@ -81,8 +81,8 @@
   path: 2
   path: 1
   sourceFile: test
-  begin: 1851
-  end: 1860
+  begin: 1779
+  end: 1788
 }
 annotation: {
   path: 4
@@ -90,8 +90,8 @@
   path: 2
   path: 2
   sourceFile: test
-  begin: 1901
-  end: 1905
+  begin: 1829
+  end: 1833
 }
 annotation: {
   path: 4
@@ -99,8 +99,8 @@
   path: 2
   path: 2
   sourceFile: test
-  begin: 1932
-  end: 1936
+  begin: 1860
+  end: 1864
 }
 annotation: {
   path: 4
@@ -108,8 +108,8 @@
   path: 2
   path: 2
   sourceFile: test
-  begin: 1989
-  end: 1996
+  begin: 1917
+  end: 1924
 }
 annotation: {
   path: 4
@@ -117,6 +117,6 @@
   path: 2
   path: 2
   sourceFile: test
-  begin: 2019
-  end: 2028
+  begin: 1947
+  end: 1956
 }
diff --git a/protoc_plugin/test/goldens/service.pb b/protoc_plugin/test/goldens/service.pb
index b56c969..e719f50 100644
--- a/protoc_plugin/test/goldens/service.pb
+++ b/protoc_plugin/test/goldens/service.pb
@@ -6,7 +6,7 @@
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
 import 'dart:async' as $async;
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
diff --git a/protoc_plugin/test/goldens/service.pbserver b/protoc_plugin/test/goldens/service.pbserver
index 6e44144..095c6d7 100644
--- a/protoc_plugin/test/goldens/service.pbserver
+++ b/protoc_plugin/test/goldens/service.pbserver
@@ -9,7 +9,7 @@
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
-import 'dart:core' as $core show String, Map, ArgumentError, dynamic;
+import 'dart:core' as $core;
 import 'test.pb.dart' as $0;
 import 'test.pbjson.dart';
 
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pb b/protoc_plugin/test/goldens/topLevelEnum.pb
index 6c93b39..1c93619 100644
--- a/protoc_plugin/test/goldens/topLevelEnum.pb
+++ b/protoc_plugin/test/goldens/topLevelEnum.pb
@@ -5,7 +5,7 @@
 // @dart = 2.3
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
+import 'dart:core' as $core;
 
 export 'test.pbenum.dart';
 
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbenum b/protoc_plugin/test/goldens/topLevelEnum.pbenum
index 4b2b465..cee6e53 100644
--- a/protoc_plugin/test/goldens/topLevelEnum.pbenum
+++ b/protoc_plugin/test/goldens/topLevelEnum.pbenum
@@ -6,7 +6,7 @@
 // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
 // ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME
-import 'dart:core' as $core show int, dynamic, String, List, Map;
+import 'dart:core' as $core;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 class PhoneType extends $pb.ProtobufEnum {
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta b/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta
index 603e31a..8a767c1 100644
--- a/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta
+++ b/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta
@@ -2,8 +2,8 @@
   path: 5
   path: 0
   sourceFile: test
-  begin: 394
-  end: 403
+  begin: 357
+  end: 366
 }
 annotation: {
   path: 5
@@ -11,8 +11,8 @@
   path: 2
   path: 0
   sourceFile: test
-  begin: 456
-  end: 462
+  begin: 419
+  end: 425
 }
 annotation: {
   path: 5
@@ -20,8 +20,8 @@
   path: 2
   path: 1
   sourceFile: test
-  begin: 516
-  end: 520
+  begin: 479
+  end: 483
 }
 annotation: {
   path: 5
@@ -29,8 +29,8 @@
   path: 2
   path: 2
   sourceFile: test
-  begin: 572
-  end: 576
+  begin: 535
+  end: 539
 }
 annotation: {
   path: 5
@@ -38,6 +38,6 @@
   path: 2
   path: 3
   sourceFile: test
-  begin: 629
-  end: 637
+  begin: 592
+  end: 600
 }
diff --git a/protobuf/test/mirror_util.dart b/protoc_plugin/test/mirror_util.dart
similarity index 100%
rename from protobuf/test/mirror_util.dart
rename to protoc_plugin/test/mirror_util.dart
diff --git a/protobuf/test/reserved_names_test.dart b/protoc_plugin/test/reserved_names_test.dart
similarity index 97%
rename from protobuf/test/reserved_names_test.dart
rename to protoc_plugin/test/reserved_names_test.dart
index 6c3dd6c..de682f6 100755
--- a/protobuf/test/reserved_names_test.dart
+++ b/protoc_plugin/test/reserved_names_test.dart
@@ -10,7 +10,7 @@
 
 import 'package:protobuf/meta.dart'
     show GeneratedMessage_reservedNames, ProtobufEnum_reservedNames;
-import 'package:protobuf/mixins_meta.dart' show findMixin;
+import 'package:protoc_plugin/mixins.dart' show findMixin;
 
 import 'mirror_util.dart' show findMemberNames;