summaryrefslogtreecommitdiff
path: root/android-gradle-jps
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-09-17 13:31:01 -0700
committerTor Norbye <tnorbye@google.com>2013-09-17 13:31:01 -0700
commitac1a140f12ea39ec3eb4d6d6276ebd786c3fd517 (patch)
tree1be7ded0b86e31c5f22a12d2e2e542732dc04fac /android-gradle-jps
parentf539500783a60e47d01f80e092e671b48705af4b (diff)
downloadidea-ac1a140f12ea39ec3eb4d6d6276ebd786c3fd517.tar.gz
60050: Build fails if project path contains two dashes
This changeset makes the error parser (which handles embedded path references pointing to the pre-merge sources of XML files) handle file URLs that contain escaped characters, such as %2D for dashes -- which is necessary when paths contain double dashes, since those are not valid in XML comments. (There is a corresponding fix in the merge writer used by the android plugin which ensures that paths are escaped when necessary.) Change-Id: I53d7af26ed1dacf96cf9018edfa5729b7b21f605
Diffstat (limited to 'android-gradle-jps')
-rw-r--r--android-gradle-jps/src/com/android/tools/idea/jps/output/parser/aapt/AbstractAaptOutputParser.java29
-rw-r--r--android-gradle-jps/testSrc/com/android/tools/idea/jps/output/parser/GradleErrorOutputParserTest.java201
2 files changed, 227 insertions, 3 deletions
diff --git a/android-gradle-jps/src/com/android/tools/idea/jps/output/parser/aapt/AbstractAaptOutputParser.java b/android-gradle-jps/src/com/android/tools/idea/jps/output/parser/aapt/AbstractAaptOutputParser.java
index d4b21988130..c4efa3e96d7 100644
--- a/android-gradle-jps/src/com/android/tools/idea/jps/output/parser/aapt/AbstractAaptOutputParser.java
+++ b/android-gradle-jps/src/com/android/tools/idea/jps/output/parser/aapt/AbstractAaptOutputParser.java
@@ -34,7 +34,6 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
-import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -327,14 +326,38 @@ public abstract class AbstractAaptOutputParser implements CompilerOutputParser {
return null;
}
String sourcePath = document.subsequence(start, end).toString();
+ File sourceFile;
if (sourcePath.startsWith("file:")) {
if (!sourcePath.startsWith("file://")) {
- // Both JpsPathUril.urlToPath and new File(URI) can only handle file://
+ // Both JpsPathUtil.urlToPath and new File(URI) can only handle file://
sourcePath = "file://" + sourcePath.substring("file:".length());
}
+ String originalPath = sourcePath;
sourcePath = JpsPathUtil.urlToPath(sourcePath);
+ sourceFile = new File(sourcePath);
+ if (!sourceFile.exists()) {
+ // JpsPathUtil.urlToPath just chops off the prefix; try a little harder
+ // for example to decode %2D's which are used by the MergedResourceWriter to
+ // encode --'s in the path, since those are invalid in XML comments
+ try {
+ URL url = new URL(originalPath);
+ try {
+ sourceFile = new File(url.toURI());
+ }
+ catch (IllegalArgumentException e) {
+ LOG.warn("Invalid file URL: " + originalPath);
+ }
+ catch (URISyntaxException e) {
+ sourceFile = new File(url.getPath());
+ }
+ }
+ catch (MalformedURLException e) {
+ LOG.warn("Invalid file URL: " + originalPath);
+ }
+ }
+ } else {
+ sourceFile = new File(sourcePath);
}
- File sourceFile = new File(sourcePath);
if (isValueFile) {
// Look up the line number
diff --git a/android-gradle-jps/testSrc/com/android/tools/idea/jps/output/parser/GradleErrorOutputParserTest.java b/android-gradle-jps/testSrc/com/android/tools/idea/jps/output/parser/GradleErrorOutputParserTest.java
index f5f8e612fee..81f005f7476 100644
--- a/android-gradle-jps/testSrc/com/android/tools/idea/jps/output/parser/GradleErrorOutputParserTest.java
+++ b/android-gradle-jps/testSrc/com/android/tools/idea/jps/output/parser/GradleErrorOutputParserTest.java
@@ -36,6 +36,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Locale;
+import static com.android.ide.common.res2.MergedResourceWriter.createPathComment;
+
/**
* Tests for {@link GradleErrorOutputParser}.
*/
@@ -857,4 +859,203 @@ public class GradleErrorOutputParserTest extends TestCase {
source.delete();
tempDir.delete();
}
+
+ public void testDashes() throws Exception {
+ File tempDir = Files.createTempDir();
+ File dir = new File(tempDir, "My -- Q&A< Dir"); // path which should force encoding of path chars, see for example issue 60050
+ dir.mkdirs();
+ sourceFile = new File(dir, "values.xml"); // Name matters for position search
+ sourceFilePath = FileUtil.toSystemIndependentName(sourceFile.getAbsolutePath());
+ File source = new File(dir, "dimens.xml");
+ Files.write("<resources>\n" +
+ " <!-- Default screen margins, per the Android Design guidelines. -->\n" +
+ " <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n" +
+ " <dimen name=\"activity_vertical_margin\">16dp</dimen>\n" +
+ " <dimen name=\"new_name\">50</dimen>\n" +
+ "</resources>", source, Charsets.UTF_8);
+ source.deleteOnExit();
+ Files.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<resources>\n" +
+ " <!-- From: file:/Users/unittest/AndroidStudioProjects/BlankProject1Project/BlankProject1/build/exploded-bundles/ComAndroidSupportAppcompatV71800.aar/res/values/values.xml -->\n" +
+ " <dimen name=\"abc_action_bar_default_height\">48dip</dimen>\n" +
+ " <dimen name=\"abc_action_bar_icon_vertical_padding\">8dip</dimen>\n" +
+ " <!-- " + createPathComment(source) + " -->\n" +
+ " <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n" +
+ " <dimen name=\"activity_vertical_margin\">16dp</dimen>\n" +
+ " <dimen name=\"ok\">50dp</dimen>\n" +
+ " <dimen name=\"new_name\">50</dimen>\n" +
+ " <!-- From: file:/Users/unittest/AndroidStudioProjects/BlankProject1Project/BlankProject1/build/exploded-bundles/ComAndroidSupportAppcompatV71800.aar/res/values/values.xml -->\n" +
+ " <item name=\"action_bar_activity_content\" type=\"id\"/>\n" +
+ " <item name=\"action_menu_divider\" type=\"id\"/>\n" +
+ " <item name=\"action_menu_presenter\" type=\"id\"/>\n" +
+ " <item name=\"home\" type=\"id\"/>\n" +
+ "</resources>\n", sourceFile, Charsets.UTF_8);
+
+ // TODO: Test layout too
+
+ String output =
+ "Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0\n" +
+ ":BlankProject1:prepareComAndroidSupportAppcompatV71800Library UP-TO-DATE\n" +
+ ":BlankProject1:prepareDebugDependencies\n" +
+ ":BlankProject1:mergeDebugAssets UP-TO-DATE\n" +
+ ":BlankProject1:compileDebugRenderscript UP-TO-DATE\n" +
+ ":BlankProject1:mergeDebugResources UP-TO-DATE\n" +
+ ":BlankProject1:processDebugManifest UP-TO-DATE\n" +
+ ":BlankProject1:processDebugResources\n" +
+ sourceFilePath + ":10: error: Error: Integer types not allowed (at 'new_name' with value '50').\n" +
+ ":BlankProject1:processDebugResources FAILED\n" +
+ "\n" +
+ "FAILURE: Build failed with an exception.\n" +
+ "\n" +
+ "* What went wrong:\n" +
+ "Execution failed for task ':BlankProject1:processDebugResources'.\n" +
+ "> Failed to run command:\n" +
+ " \t/Users/tnorbye/dev/sdks/build-tools/18.0.1/aapt package -f --no-crunch -I ...\n" +
+ " Error Code:\n" +
+ " \t1\n" +
+ " Output:\n" +
+ " \t" + sourceFilePath + ":10: error: Error: Integer types not allowed (at 'new_name' with value '50').\n" +
+ "\n" +
+ "\n" +
+ "* Try:\n" +
+ "Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.\n" +
+ "\n" +
+ "BUILD FAILED\n" +
+ "\n" +
+ "Total time: 5.435 secs";
+
+ assertEquals("0: Info:Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0\n" +
+ "1: Info::BlankProject1:prepareComAndroidSupportAppcompatV71800Library UP-TO-DATE\n" +
+ "2: Info::BlankProject1:prepareDebugDependencies\n" +
+ "3: Info::BlankProject1:mergeDebugAssets UP-TO-DATE\n" +
+ "4: Info::BlankProject1:compileDebugRenderscript UP-TO-DATE\n" +
+ "5: Info::BlankProject1:mergeDebugResources UP-TO-DATE\n" +
+ "6: Info::BlankProject1:processDebugManifest UP-TO-DATE\n" +
+ "7: Info::BlankProject1:processDebugResources\n" +
+ "8: Gradle:Error:Integer types not allowed (at 'new_name' with value '50').\n" +
+ "\t" + FileUtil.toSystemIndependentName(source.getPath()) + ":5:28\n" +
+ "9: Info::BlankProject1:processDebugResources FAILED\n" +
+ "10: Gradle:Error:Error while executing aapt command\n" +
+ "11: Gradle:Error:Integer types not allowed (at 'new_name' with value '50').\n" +
+ "\t" + FileUtil.toSystemIndependentName(source.getPath()) + ":5:28\n" +
+ "12: Gradle:Error:Execution failed for task ':BlankProject1:processDebugResources'.\n" +
+ "13: Info:BUILD FAILED\n" +
+ "14: Info:Total time: 5.435 secs\n",
+ toString(parser.parseErrorOutput(output)));
+
+ sourceFile.delete();
+ source.delete();
+ dir.delete();
+ tempDir.delete();
+ }
+
+ public void testLayoutFileSuffix() throws Exception {
+ File tempDir = Files.createTempDir();
+ sourceFile = new File(tempDir, "layout.xml");
+ sourceFilePath = FileUtil.toSystemIndependentName(sourceFile.getAbsolutePath());
+ File source = new File(tempDir, "layout.xml");
+ Files.write("<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
+ " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
+ " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
+ " android:paddingBottom=\"@dimen/activity_vertical_margin\"\n" +
+ " tools:context=\".MainActivity\">\n" +
+ "\n" +
+ "\n" +
+ " <Button\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:hint=\"fy faen\"\n" +
+ " android:text=\"@string/hello_world\"\n" +
+ " android:slayout_alignParentTop=\"true\"\n" +
+ " android:layout_alignParentLeft=\"true\" />\n" +
+ "\n" +
+ "</RelativeLayout>\n", source, Charsets.UTF_8);
+ source.deleteOnExit();
+ Files.write("<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
+ " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
+ " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
+ " android:paddingBottom=\"@dimen/activity_vertical_margin\"\n" +
+ " tools:context=\".MainActivity\">\n" +
+ "\n" +
+ " <!--style=\"@style/Buttons\"-->\n" +
+ " <Button\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:hint=\"fy faen\"\n" +
+ " android:text=\"@string/hello_world\"\n" +
+ " android:slayout_alignParentTop=\"true\"\n" +
+ " android:layout_alignParentLeft=\"true\" />\n" +
+ "\n" +
+ "</RelativeLayout>\n" +
+ "<!-- " + createPathComment(source) + " -->", sourceFile, Charsets.UTF_8);
+
+ String output =
+ "Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0\n" +
+ ":BlankProject1:preBuild UP-TO-DATE\n" +
+ ":BlankProject1:preDebugBuild UP-TO-DATE\n" +
+ ":BlankProject1:preReleaseBuild UP-TO-DATE\n" +
+ ":BlankProject1:prepareComAndroidSupportAppcompatV71800Library UP-TO-DATE\n" +
+ ":BlankProject1:prepareDebugDependencies\n" +
+ ":BlankProject1:compileDebugAidl UP-TO-DATE\n" +
+ ":BlankProject1:compileDebugRenderscript UP-TO-DATE\n" +
+ ":BlankProject1:generateDebugBuildConfig UP-TO-DATE\n" +
+ ":BlankProject1:mergeDebugAssets UP-TO-DATE\n" +
+ ":BlankProject1:mergeDebugResources UP-TO-DATE\n" +
+ ":BlankProject1:processDebugManifest UP-TO-DATE\n" +
+ ":BlankProject1:processDebugResources\n" +
+ sourceFilePath + ":12: error: No resource identifier found for attribute 'slayout_alignParentTop' in package 'android'\n" +
+ ":BlankProject1:processDebugResources FAILED\n" +
+ "\n" +
+ "FAILURE: Build failed with an exception.\n" +
+ "\n" +
+ "* What went wrong:\n" +
+ "Execution failed for task ':BlankProject1:processDebugResources'.\n" +
+ "> Failed to run command:\n" +
+ " \t/Users/tnorbye/dev/sdks/build-tools/18.0.1/aapt package -f --no-crunch -I ... " +
+ " Error Code:\n" +
+ " \t1\n" +
+ " Output:\n" +
+ " \t" + sourceFilePath + ":12: error: No resource identifier found for attribute 'slayout_alignParentTop' in package 'android'\n" +
+ "\n" +
+ "\n" +
+ "* Try:\n" +
+ "Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.\n" +
+ "\n" +
+ "BUILD FAILED\n";
+
+ assertEquals("0: Info:Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0\n" +
+ "1: Info::BlankProject1:preBuild UP-TO-DATE\n" +
+ "2: Info::BlankProject1:preDebugBuild UP-TO-DATE\n" +
+ "3: Info::BlankProject1:preReleaseBuild UP-TO-DATE\n" +
+ "4: Info::BlankProject1:prepareComAndroidSupportAppcompatV71800Library UP-TO-DATE\n" +
+ "5: Info::BlankProject1:prepareDebugDependencies\n" +
+ "6: Info::BlankProject1:compileDebugAidl UP-TO-DATE\n" +
+ "7: Info::BlankProject1:compileDebugRenderscript UP-TO-DATE\n" +
+ "8: Info::BlankProject1:generateDebugBuildConfig UP-TO-DATE\n" +
+ "9: Info::BlankProject1:mergeDebugAssets UP-TO-DATE\n" +
+ "10: Info::BlankProject1:mergeDebugResources UP-TO-DATE\n" +
+ "11: Info::BlankProject1:processDebugManifest UP-TO-DATE\n" +
+ "12: Info::BlankProject1:processDebugResources\n" +
+ "13: Gradle:Error:No resource identifier found for attribute 'slayout_alignParentTop' in package 'android'\n" +
+ "\t" + FileUtil.toSystemIndependentName(source.getPath()) + ":12:-1\n" +
+ "14: Info::BlankProject1:processDebugResources FAILED\n" +
+ "15: Gradle:Error:Error while executing aapt command\n" +
+ "16: Gradle:Error:No resource identifier found for attribute 'slayout_alignParentTop' in package 'android'\n" +
+ "\t" + FileUtil.toSystemIndependentName(source.getPath()) + ":12:-1\n" +
+ "17: Gradle:Error:Execution failed for task ':BlankProject1:processDebugResources'.\n" +
+ "18: Info:BUILD FAILED\n",
+ toString(parser.parseErrorOutput(output)));
+
+ sourceFile.delete();
+ source.delete();
+ tempDir.delete();
+ }
}