52407: should add a newline at the end of autogenerated xml files

Change-Id: Ia7a910e4426cf73f9ed25de9dfaf3df63cb88116
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/AndroidXmlFormattingStrategy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/AndroidXmlFormattingStrategy.java
index 94c5299..9f69e41 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/AndroidXmlFormattingStrategy.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/AndroidXmlFormattingStrategy.java
@@ -272,6 +272,7 @@
         int initialDepth = 0;
         int replaceStart;
         int replaceEnd;
+        boolean endWithNewline = false;
         if (startNode == null || endNode == null) {
             // Process the entire document
             root = domDocument;
@@ -281,6 +282,11 @@
             endNode = root;
             replaceStart = 0;
             replaceEnd = document.getLength();
+            try {
+                endWithNewline = replaceEnd > 0 && document.getChar(replaceEnd - 1) == '\n';
+            } catch (BadLocationException e) {
+                // Can't happen
+            }
         } else {
             root = DomUtilities.getCommonAncestor(startNode, endNode);
             initialDepth = root != null ? DomUtilities.getDepth(root) - 1 : 0;
@@ -337,7 +343,8 @@
         XmlFormatStyle style = guessStyle(model, domDocument);
         XmlFormatPreferences prefs = EclipseXmlFormatPreferences.create();
         String delimiter = TextUtilities.getDefaultLineDelimiter(document);
-        XmlPrettyPrinter printer = new XmlPrettyPrinter(prefs, style, delimiter);
+        XmlPrettyPrinter printer = new EclipseXmlPrettyPrinter(prefs, style, delimiter);
+        printer.setEndWithNewline(endWithNewline);
 
         if (indentationLevels != null) {
             printer.setIndentationLevels(indentationLevels);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinter.java
index d3b6803..d3f7ec8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinter.java
@@ -82,6 +82,10 @@
         if (document != null) {
             EclipseXmlPrettyPrinter printer = new EclipseXmlPrettyPrinter(prefs, style,
                     lineSeparator);
+            if (xml.endsWith("\n")) { //$NON-NLS-1$
+                printer.setEndWithNewline(true);
+            }
+
             StringBuilder sb = new StringBuilder(3 * xml.length() / 2);
             printer.prettyPrint(-1, document, null, null, sb, false /*openTagOnly*/);
             return sb.toString();
@@ -92,9 +96,9 @@
     }
 
     @NonNull
-    public static String prettyPrint(@NonNull Node node) {
+    public static String prettyPrint(@NonNull Node node, boolean endWithNewline) {
         return prettyPrint(node, EclipseXmlFormatPreferences.create(), XmlFormatStyle.get(node),
-                null);
+                null, endWithNewline);
     }
 
     private static String getDefaultLineSeparator() {
@@ -122,8 +126,10 @@
             @NonNull Node node,
             @NonNull XmlFormatPreferences prefs,
             @NonNull XmlFormatStyle style,
-            @Nullable String lineSeparator) {
+            @Nullable String lineSeparator,
+            boolean endWithNewline) {
         XmlPrettyPrinter printer = new EclipseXmlPrettyPrinter(prefs, style, lineSeparator);
+        printer.setEndWithNewline(endWithNewline);
         StringBuilder sb = new StringBuilder(1000);
         printer.prettyPrint(-1, node, null, null, sb, false /*openTagOnly*/);
         String xml = sb.toString();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java
index c11268c..d4cc6df 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java
@@ -590,8 +590,13 @@
         if (resFolder != null) {
             mConfiguration.setEditedConfig(resFolder.getConfiguration());
         } else {
-            mConfiguration.setEditedConfig(FolderConfiguration.getConfig(
-                    parent.getName().split(RES_QUALIFIER_SEP)));
+            FolderConfiguration config = FolderConfiguration.getConfig(
+                    parent.getName().split(RES_QUALIFIER_SEP));
+            if (config != null) {
+                mConfiguration.setEditedConfig(config);
+            } else {
+                mConfiguration.setEditedConfig(new FolderConfiguration());
+            }
         }
 
         onXmlModelLoaded();
@@ -745,8 +750,13 @@
                         if (resFolder != null) {
                             mConfiguration.setEditedConfig(resFolder.getConfiguration());
                         } else {
-                            mConfiguration.setEditedConfig(FolderConfiguration.getConfig(
-                                    parent.getName().split(RES_QUALIFIER_SEP)));
+                            FolderConfiguration config = FolderConfiguration.getConfig(
+                                    parent.getName().split(RES_QUALIFIER_SEP));
+                            if (config != null) {
+                                mConfiguration.setEditedConfig(config);
+                            } else {
+                                mConfiguration.setEditedConfig(new FolderConfiguration());
+                            }
                         }
                     }
 
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreviewList.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreviewList.java
index d3c4fab..f5d3290 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreviewList.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreviewList.java
@@ -107,7 +107,7 @@
             for (ConfigurationDescription description : mList) {
                 description.toXml(document);
             }
-            String xml = EclipseXmlPrettyPrinter.prettyPrint(document);
+            String xml = EclipseXmlPrettyPrinter.prettyPrint(document, true);
             Files.write(xml, file, Charsets.UTF_8);
         }
     }
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
index a775686..0e56bdf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java
@@ -356,7 +356,7 @@
         String xml = EclipseXmlPrettyPrinter.prettyPrint(
                 tempDocument.getDocumentElement(),
                 EclipseXmlFormatPreferences.create(),
-                XmlFormatStyle.LAYOUT, null);
+                XmlFormatStyle.LAYOUT, null, false);
 
         TextEdit replace = new ReplaceEdit(mSelectionStart, mSelectionEnd - mSelectionStart, xml);
         rootEdit.addChild(replace);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
index eb3d94a..bd9c0fa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
@@ -706,7 +706,8 @@
         if (ok) {
             if (modified) {
                 contents = EclipseXmlPrettyPrinter.prettyPrint(currentDocument,
-                        EclipseXmlFormatPreferences.create(), formatStyle, null);
+                        EclipseXmlFormatPreferences.create(), formatStyle, null,
+                        currentXml.endsWith("\n")); //$NON-NLS-1$
             }
         } else {
             // Just insert into file along with comment, using the "standard" conflict
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinterTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinterTest.java
index 8fc8dd1..ac5fd01 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinterTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/EclipseXmlPrettyPrinterTest.java
@@ -63,6 +63,7 @@
         XmlFormatStyle style = AndroidXmlFormattingStrategy.guessStyle(model, document);
 
         EclipseXmlPrettyPrinter printer = new EclipseXmlPrettyPrinter(prefs, style, delimiter);
+        printer.setEndWithNewline(xml.endsWith("\n"));
 
         StringBuilder sb = new StringBuilder(1000);
         Node startNode = document;
@@ -180,7 +181,7 @@
                 "    <item name=\"title_container\" type=\"id\"/>\n" +
                 "    <item name=\"title_logo\" type=\"id\"/>\n" +
                 "\n" +
-                "</resources>");
+                "</resources>\n");
     }
 
     public void testResources() throws Exception {
@@ -876,7 +877,7 @@
                 "    <string name=\"untitled2\">&lt;untitled2&gt;</string>\n" +
                 "    <string name=\"untitled3\">&apos;untitled3&quot;</string>\n" +
                 "\n" +
-                "</resources>");
+                "</resources>\n");
     }
 
     public void testCData1() throws Exception {
@@ -954,4 +955,24 @@
                 "    android:layout_width=\"match_parent\"\n" +
                 "    android:layout_height=\"match_parent\" />\n");
     }
+
+    public void testPreserveLastNewline() throws Exception {
+        checkFormat(
+                "res/values/strings.xml",
+                "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+                "<resources>\n" +
+                "<string name=\"progress_completed_export_all\">The database has " +
+                "<b>successfully</b> been exported into: <br /><br /><font size=\"14\">" +
+                "\\\"<i>%s</i>\\\"</font></string>" +
+                "</resources>\n",
+
+                "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+                "<resources>\n" +
+                "\n" +
+                "    <string name=\"progress_completed_export_all\">The database has " +
+                "<b>successfully</b> been exported into: <br /><br /><font size=\"14\">" +
+                "\\\"<i>%s</i>\\\"</font></string>\n" +
+                "\n" +
+                "</resources>\n");
+    }
 }