Give rewrite_intl_messages.dart the ability to rewrite sources to remove transformer usage.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130771346
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a33e824..9fd0014 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@
  * Add support for currency in compact number formats.
  * Added support for "Q" and "QQ" numeric quarter formatting, which fixes "QQQ"
    and "QQQQ" in the zh_CN locale.
+ * As part of deprecating transformer usage, allow `rewrite_intl_messages.dart`
+   to add names and arguments to messages with parameters. Make the transformer
+   not generate names for zero-argument methods and just use the name+meaning instead.
 
 ## 0.13.0
  * Add support for compact number formats ("1.2K") and for significant digits in
diff --git a/lib/extract_messages.dart b/lib/extract_messages.dart
index e9c13b8..306b5d4 100644
--- a/lib/extract_messages.dart
+++ b/lib/extract_messages.dart
@@ -23,6 +23,7 @@
 
 import 'package:analyzer/analyzer.dart';
 import 'package:intl/src/intl_message.dart';
+import 'package:intl/src/intl_helpers.dart';
 
 /// A function that takes a message and does something useful with it.
 typedef void OnMessage(String message);
@@ -248,7 +249,6 @@
     var message = new MainMessage();
     message.sourcePosition = node.offset;
     message.endPosition = node.end;
-
     message.arguments =
         parameters.parameters.map((x) => x.identifier.name).toList();
     var arguments = node.argumentList.arguments;
@@ -266,16 +266,19 @@
           : basicValue;
       setAttribute(message, name, value);
     }
-    if (message.name == "") {
-      if (generateNameAndArgs) {
+    // We only rewrite messages with parameters, otherwise we use the literal
+    // string as the name and no arguments are necessary.
+    if (!message.hasName) {
+      if (generateNameAndArgs && message.arguments.isNotEmpty) {
         // Always try for class_method if this is a class method and
-        // transforming.
+        // generating names/args.
         message.name = Message.classPlusMethodName(node, name) ?? name;
       } else if (arguments.first is SimpleStringLiteral ||
           arguments.first is AdjacentStrings) {
-        // If there's no name, and the message text is a single string, use it
-        // as the name
-        message.name = (arguments.first as StringLiteral).stringValue;
+        // If there's no name, and the message text is a simple string, compute
+        // a name based on that plus meaning, if present.
+        var simpleName = (arguments.first as StringLiteral).stringValue;
+        message.name = computeMessageName(message.name, simpleName, message.meaning);
       }
     }
     return message;
diff --git a/lib/intl.dart b/lib/intl.dart
index 62db076..19b5a3b 100644
--- a/lib/intl.dart
+++ b/lib/intl.dart
@@ -171,11 +171,11 @@
           String name,
           List args,
           String meaning}) =>
-      _message(message_str, locale, name, args);
+      _message(message_str, locale, name, args, meaning);
 
   /// Omit the compile-time only parameters so dart2js can see to drop them.
-  static _message(String message_str, String locale, String name, List args) {
-    return messageLookup.lookupMessage(message_str, locale, name, args);
+  static _message(String message_str, String locale, String name, List args, String meaning) {
+    return messageLookup.lookupMessage(message_str, locale, name, args, meaning);
   }
 
   /// Return the locale for this instance. If none was set, the locale will
diff --git a/lib/message_lookup_by_library.dart b/lib/message_lookup_by_library.dart
index a3d89ac..d596c03 100644
--- a/lib/message_lookup_by_library.dart
+++ b/lib/message_lookup_by_library.dart
@@ -38,7 +38,7 @@
   /// If nothing is found, return [message_str]. The [desc] and [examples]
   /// parameters are ignored
   String lookupMessage(
-      String message_str, String locale, String name, List args,
+      String message_str, String locale, String name, List args, String meaning,
       {MessageIfAbsent ifAbsent: _useOriginal}) {
     // If passed null, use the default.
     var knownLocale = locale ?? Intl.getCurrentLocale();
@@ -50,9 +50,8 @@
     if (messages == null) {
       return ifAbsent(message_str, args);
     }
-    // If the name is blank, use the message as a key
     return messages.lookupMessage(
-        message_str, locale, name ?? message_str, args,
+        message_str, locale, name, args, meaning,
         ifAbsent: ifAbsent);
   }
 
@@ -112,11 +111,12 @@
   /// will be extracted automatically but for the time being it must be passed
   /// explicitly in the [name] and [args] arguments.
   String lookupMessage(
-      String message_str, String locale, String name, List args,
+      String message_str, String locale, String name, List args, String meaning,
       {MessageIfAbsent ifAbsent}) {
     var notFound = false;
-    if (name == null) notFound = true;
-    var function = this[name];
+    var actualName = computeMessageName(name, message_str, meaning);
+    if (actualName == null) notFound = true;
+    var function = this[actualName];
     notFound = notFound || (function == null);
     if (notFound) {
       return ifAbsent == null ? message_str : ifAbsent(message_str, args);
diff --git a/lib/src/intl_helpers.dart b/lib/src/intl_helpers.dart
index 5556b7a..8e3c0f0 100644
--- a/lib/src/intl_helpers.dart
+++ b/lib/src/intl_helpers.dart
@@ -25,7 +25,7 @@
       (key == 'en_US') ? fallbackData : _throwException();
 
   String lookupMessage(
-          String message_str, String locale, String name, List args,
+      String message_str, String locale, String name, List args, String meaning,
           {MessageIfAbsent ifAbsent}) =>
       message_str;
 
@@ -47,7 +47,7 @@
 
 abstract class MessageLookup {
   String lookupMessage(
-      String message_str, String locale, String name, List args,
+      String message_str, String locale, String name, List args, String meaning,
       {MessageIfAbsent ifAbsent});
   void addLocale(String localeName, Function findLocale);
 }
@@ -77,3 +77,11 @@
     messageLookup = lookupFunction();
   }
 }
+
+  /// If a message is a string literal without interpolation, compute
+  /// a name based on that and the meaning, if present.
+  String computeMessageName(String name, String message_str, String meaning) {
+     if (name != null && name != "") return name;
+     var simpleName = message_str;
+     return meaning == null ? simpleName : "${simpleName}_${meaning}";
+  }
diff --git a/lib/src/intl_message.dart b/lib/src/intl_message.dart
index b242b15..a52fedd 100644
--- a/lib/src/intl_message.dart
+++ b/lib/src/intl_message.dart
@@ -31,6 +31,7 @@
 /// used to generate the code representation above.
 library intl_message;
 
+import 'dart:convert';
 import 'package:analyzer/analyzer.dart';
 
 /// A default function for the [Message.expanded] method.
@@ -361,12 +362,13 @@
 
   /// If the message was not given a name, we use the entire message string as
   /// the name.
-  String get name => _name == null ? computeName() : _name;
+  String get name => _name ?? "";
   set name(String newName) {
     _name = newName;
   }
 
-  String computeName() => name = expanded((msg, chunk) => "");
+  /// Does this message have an assigned name.
+  bool get hasName => _name != null;
 
   /// Return the full message, with any interpolation expressions transformed
   /// by [f] and all the results concatenated. The chunk argument to [f] may be
@@ -406,11 +408,16 @@
   }
 
   String toOriginalCode() {
-    var out = new StringBuffer()..write('Intl.message("');
+    var out = new StringBuffer()..write("Intl.message('");
     out.write(expanded(turnInterpolationBackIntoStringForm));
-    out.write('", ');
-    out.write('name: "$name", ');
-    out.write(locale == null ? "" : 'locale: "$locale", ');
+    out.write("', ");
+    out.write("name: '$name', ");
+    out.write(locale == null ? "" : "locale: '$locale', ");
+    out.write(description == null ? "" : "desc: '${escapeAndValidateString(description)}', ");
+    // json is already mostly-escaped, but we need to handle interpolations.
+    var json = JSON.encode(examples).replaceAll(r"$", r"\$");
+    out.write(examples == null ? "" : "examples: const ${json}, ");
+    out.write(meaning == null ? "" : "meaning: '${escapeAndValidateString(meaning)}', ");
     out.write("args: [${arguments.join(', ')}]");
     out.write(")");
     return out.toString();
diff --git a/lib/src/message_rewriter.dart b/lib/src/message_rewriter.dart
index 10f7fc2..0d512bd 100644
--- a/lib/src/message_rewriter.dart
+++ b/lib/src/message_rewriter.dart
@@ -20,11 +20,13 @@
   var start = 0;
   var newSource = new StringBuffer();
   for (var message in messages) {
-    newSource.write(source.substring(start, message.sourcePosition));
+    if (message.arguments.isNotEmpty) {
+      newSource.write(source.substring(start, message.sourcePosition));
     // TODO(alanknight): We could generate more efficient code than the
     // original here, dispatching more directly to the MessageLookup.
     newSource.write(message.toOriginalCode());
     start = message.endPosition;
+    }
   }
   newSource.write(source.substring(start));
   return newSource.toString();