aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java54
-rw-r--r--draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java37
-rw-r--r--eclipse/features/com.android.ide.eclipse.adt/feature.xml1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/.classpath4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml33
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java54
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java1194
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java285
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java103
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java)5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java)3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java155
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java210
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java110
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java21
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java8
-rw-r--r--ninepatch/src/com/android/ninepatch/NinePatch.java96
34 files changed, 1243 insertions, 1213 deletions
diff --git a/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java b/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
index 6901c98..84b96a5 100644
--- a/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
+++ b/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
@@ -478,6 +478,14 @@ class ImageEditorPanel extends JPanel {
start = rect.x;
}
}
+ } else {
+ int start = -1;
+ for (Rectangle rect : patches) {
+ if (rect.x > start) {
+ horizontalPatchesSum += rect.width;
+ start = rect.x;
+ }
+ }
}
verticalPatchesSum = 0;
@@ -489,6 +497,14 @@ class ImageEditorPanel extends JPanel {
start = rect.y;
}
}
+ } else {
+ int start = -1;
+ for (Rectangle rect : patches) {
+ if (rect.y > start) {
+ verticalPatchesSum += rect.height;
+ start = rect.y;
+ }
+ }
}
setSize(size);
@@ -528,8 +544,7 @@ class ImageEditorPanel extends JPanel {
x = 0;
y = 0;
- if (patches.size() == 0 || horizontalPatches.size() == 0 ||
- verticalPatches.size() == 0) {
+ if (patches.size() == 0) {
g.drawImage(image, 0, 0, scaledWidth, scaledHeight, null);
g2.dispose();
return;
@@ -1028,7 +1043,15 @@ class ImageEditorPanel extends JPanel {
horizontalPatches = getRectangles(left.first, top.second);
verticalPatches = getRectangles(left.second, top.first);
} else {
- horizontalPatches = verticalPatches = new ArrayList<Rectangle>(0);
+ if (top.first.size() > 0) {
+ horizontalPatches = new ArrayList<Rectangle>(0);
+ verticalPatches = getVerticalRectangles(top.first);
+ } else if (left.first.size() > 0) {
+ horizontalPatches = getHorizontalRectangles(left.first);
+ verticalPatches = new ArrayList<Rectangle>(0);
+ } else {
+ horizontalPatches = verticalPatches = new ArrayList<Rectangle>(0);
+ }
}
row = GraphicsUtilities.getPixels(image, 0, height - 1, width, 1, row);
@@ -1041,6 +1064,28 @@ class ImageEditorPanel extends JPanel {
verticalPadding = getPadding(left.first);
}
+ private List<Rectangle> getVerticalRectangles(List<Pair<Integer>> topPairs) {
+ List<Rectangle> rectangles = new ArrayList<Rectangle>();
+ for (Pair<Integer> top : topPairs) {
+ int x = top.first;
+ int width = top.second - top.first;
+
+ rectangles.add(new Rectangle(x, 1, width, image.getHeight() - 2));
+ }
+ return rectangles;
+ }
+
+ private List<Rectangle> getHorizontalRectangles(List<Pair<Integer>> leftPairs) {
+ List<Rectangle> rectangles = new ArrayList<Rectangle>();
+ for (Pair<Integer> left : leftPairs) {
+ int y = left.first;
+ int height = left.second - left.first;
+
+ rectangles.add(new Rectangle(1, y, image.getWidth() - 2, height));
+ }
+ return rectangles;
+ }
+
private Pair<Integer> getPadding(List<Pair<Integer>> pairs) {
if (pairs.size() == 0) {
return new Pair<Integer>(0, 0);
@@ -1063,7 +1108,7 @@ class ImageEditorPanel extends JPanel {
for (Pair<Integer> left : leftPairs) {
int y = left.first;
int height = left.second - left.first;
- for (Pair<Integer> top: topPairs) {
+ for (Pair<Integer> top : topPairs) {
int x = top.first;
int width = top.second - top.first;
@@ -1108,6 +1153,7 @@ class ImageEditorPanel extends JPanel {
startWithPatch[0] = true;
fixed.clear();
}
+
return new Pair<List<Pair<Integer>>>(fixed, patches);
}
diff --git a/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java b/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
index a62884f..f14cd77 100644
--- a/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
+++ b/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
@@ -36,25 +36,48 @@ class ImageTransferHandler extends TransferHandler {
@Override
public boolean importData(JComponent component, Transferable transferable) {
try {
- Object data = transferable.getTransferData(DataFlavor.javaFileListFlavor);
- //noinspection unchecked
- final File file = ((List<File>) data).get(0);
- mainFrame.open(file).execute();
+ for (DataFlavor flavor : transferable.getTransferDataFlavors()) {
+ if (flavor.isFlavorJavaFileListType()) {
+ Object data = transferable.getTransferData(DataFlavor.javaFileListFlavor);
+ //noinspection unchecked
+ final File file = ((List<File>) data).get(0);
+ mainFrame.open(file).execute();
+ return true;
+ } else if (flavor.isFlavorTextType()) {
+ if (flavor.getRepresentationClass() == String.class) {
+ String mime = flavor.getMimeType();
+ DataFlavor flave = new DataFlavor(mime);
+ Object data = transferable.getTransferData(flave);
+ final String path = convertPath(data.toString());
+ mainFrame.open(new File(path)).execute();
+ return true;
+ }
+ }
+ }
} catch (UnsupportedFlavorException e) {
- return false;
+ // Ignore
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
}
- return true;
+ return false;
+ }
+
+ private static String convertPath(String path) {
+ if (path.startsWith("file://")) path = path.substring("file://".length());
+ if (path.indexOf('\n') != -1) path = path.substring(0, path.indexOf('\n'));
+ if (path.indexOf('\r') != -1) path = path.substring(0, path.indexOf('\r'));
+ return path;
}
@Override
public boolean canImport(JComponent component, DataFlavor[] dataFlavors) {
for (DataFlavor flavor : dataFlavors) {
- if (flavor.isFlavorJavaFileListType()) {
+ if (flavor.isFlavorJavaFileListType() || flavor.isFlavorTextType()) {
return true;
}
}
diff --git a/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index b9e2c7f..97bc8b1 100644
--- a/eclipse/features/com.android.ide.eclipse.adt/feature.xml
+++ b/eclipse/features/com.android.ide.eclipse.adt/feature.xml
@@ -134,6 +134,7 @@ This Agreement is governed by the laws of the State of New York and the intellec
<import plugin="org.eclipse.wst.sse.ui"/>
<import plugin="org.eclipse.wst.xml.core"/>
<import plugin="org.eclipse.wst.xml.ui"/>
+ <import plugin="org.eclipse.jdt.junit"/>
</requires>
<plugin
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index c3c8c10..a24fc87 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -10,7 +10,7 @@
<classpathentry kind="lib" path="layoutlib_api.jar"/>
<classpathentry kind="lib" path="layoutlib_utils.jar"/>
<classpathentry kind="lib" path="ninepatch.jar"/>
- <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
- <classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
+ <classpathentry kind="lib" path="sdklib.jar" sourcepath="/SdkLib"/>
+ <classpathentry kind="lib" path="sdkuilib.jar" sourcepath="/SdkUiLib"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index a464d5c..3750f66 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -39,10 +39,12 @@ Require-Bundle: com.android.ide.eclipse.ddms,
org.eclipse.wst.sse.core,
org.eclipse.wst.sse.ui,
org.eclipse.wst.xml.core,
- org.eclipse.wst.xml.ui
+ org.eclipse.wst.xml.ui,
+ org.eclipse.jdt.junit
Eclipse-LazyStart: true
Export-Package: com.android.ide.eclipse.adt,
com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.adt.launch;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests",
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index d6c9ac1..4dfcc07 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -111,7 +111,7 @@
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
- delegate="com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate"
+ delegate="com.android.ide.eclipse.adt.launch.LaunchConfigDelegate"
delegateDescription="The Android Application Launcher supports running and debugging remote Android applications on devices or emulators."
delegateName="Android Launcher"
id="com.android.ide.eclipse.adt.debug.LaunchConfigType"
@@ -132,7 +132,7 @@
<extension
point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
- class="com.android.ide.eclipse.adt.debug.ui.LaunchConfigTabGroup"
+ class="com.android.ide.eclipse.adt.launch.LaunchConfigTabGroup"
description="Android Application"
id="com.android.ide.eclipse.adt.debug.LaunchConfigTabGroup"
type="com.android.ide.eclipse.adt.debug.LaunchConfigType"/>
@@ -140,8 +140,8 @@
<extension
point="org.eclipse.debug.ui.launchShortcuts">
<shortcut
- category="com.android.ide.eclipse.adt.debug.LaunchConfigType"
- class="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut"
+ category="com.android.ide.eclipse.adt.launch.LaunchConfigType"
+ class="com.android.ide.eclipse.adt.launch.LaunchShortcut"
icon="icons/android.png"
id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut"
label="Android Application"
@@ -220,12 +220,6 @@
value="com.android.ide.eclipse.adt.AndroidNature">
</filter>
<action
- class="com.android.ide.eclipse.adt.project.CreateAidlImportAction"
- enablesFor="1"
- id="com.android.ide.eclipse.adt.project.CreateAidlImportAction"
- label="Create Aidl preprocess file for Parcelable classes"
- menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1"/>
- <action
class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
enablesFor="1"
id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
@@ -345,24 +339,24 @@
name="Debug Android Application"
description="Debug Android Application"
categoryId="org.eclipse.debug.ui.category.run"
- id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.debug">
+ id="com.android.ide.eclipse.adt.launch.LaunchShortcut.debug">
</command>
<command
name="Run Android Application"
description="Run Android Application"
categoryId="org.eclipse.debug.ui.category.run"
- id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.run">
+ id="com.android.ide.eclipse.adt.launch.LaunchShortcut.run">
</command>
<keyBinding
keySequence="M3+M2+A D"
contextId="org.eclipse.ui.globalScope"
- commandId="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.debug"
+ commandId="com.android.ide.eclipse.adt.launch.LaunchShortcut.debug"
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
</keyBinding>
<keyBinding
keySequence="M3+M2+A R"
contextId="org.eclipse.ui.globalScope"
- commandId="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.run"
+ commandId="com.android.ide.eclipse.adt.launch.LaunchShortcut.run"
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
</keyBinding>
</extension>
@@ -499,4 +493,15 @@
</action>
</actionSet>
</extension>
+ <extension
+ point="org.eclipse.debug.core.launchDelegates">
+ <launchDelegate
+ delegate="com.android.ide.eclipse.adt.launch.JUnitLaunchConfigDelegate"
+ delegateDescription="Removes the Android JAR from the Bootstrap Classpath"
+ id="com.android.ide.eclipse.adt.launch.JUnitLaunchConfigDelegate.launchAndroidJunit"
+ modes="run,debug"
+ name="Android JUnit"
+ type="org.eclipse.jdt.junit.launchconfig">
+ </launchDelegate>
+ </extension>
</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 61be3e5..48a21d1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -20,7 +20,7 @@ import com.android.ddmuilib.StackTracePanel;
import com.android.ddmuilib.StackTracePanel.ISourceRevealer;
import com.android.ddmuilib.console.DdmConsole;
import com.android.ddmuilib.console.IDdmConsole;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
+import com.android.ide.eclipse.adt.launch.AndroidLaunchController;
import com.android.ide.eclipse.adt.preferences.BuildPreferencePage;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.project.export.ExportWizard;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
index e2e9728..c3d5ba6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
@@ -20,15 +20,14 @@ import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.LoadStatus;
-import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.XmlErrorHandler;
import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
-import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -37,8 +36,10 @@ import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -892,25 +893,19 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
stopBuild("SDK is not loaded yet");
}
- // check the compiler compliance level.
- if (ProjectHelper.checkCompilerCompliance(project) !=
- ProjectHelper.COMPILER_COMPLIANCE_OK) {
- // we exit silently
- stopBuild(Messages.Compiler_Compliance_Error);
- }
-
- // Check that the SDK directory has been setup.
- String osSdkFolder = AdtPlugin.getOsSdkFolder();
-
- if (osSdkFolder == null || osSdkFolder.length() == 0) {
- stopBuild(Messages.No_SDK_Setup_Error);
+ // abort if there are TARGET or ADT type markers
+ IMarker[] markers = project.findMarkers(AdtConstants.MARKER_TARGET,
+ false /*includeSubtypes*/, IResource.DEPTH_ZERO);
+
+ if (markers.length > 0) {
+ stopBuild("");
}
-
- IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
- if (projectTarget == null) {
- // no target. error has been output by the container initializer:
- // exit silently.
- stopBuild("Project has no target");
+
+ markers = project.findMarkers(AdtConstants.MARKER_ADT, false /*includeSubtypes*/,
+ IResource.DEPTH_ZERO);
+
+ if (markers.length > 0) {
+ stopBuild("");
}
}
@@ -925,5 +920,22 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
throw new CoreException(new Status(IStatus.CANCEL, AdtPlugin.PLUGIN_ID,
String.format(error, args)));
}
-
+
+ /**
+ * Recursively delete all the derived resources.
+ */
+ protected void removeDerivedResources(IResource resource, IProgressMonitor monitor)
+ throws CoreException {
+ if (resource.exists()) {
+ if (resource.isDerived()) {
+ resource.delete(true, new SubProgressMonitor(monitor, 10));
+ } else if (resource.getType() == IResource.FOLDER) {
+ IFolder folder = (IFolder)resource;
+ IResource[] members = folder.members();
+ for (IResource member : members) {
+ removeDerivedResources(member, monitor);
+ }
+ }
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
index a0e446c..fb1608c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
@@ -19,7 +19,6 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.FixLaunchConfig;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
@@ -27,8 +26,8 @@ import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
-import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
@@ -36,13 +35,13 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -68,13 +67,8 @@ public class PreCompilerBuilder extends BaseBuilder {
private static final String PROPERTY_PACKAGE = "manifestPackage"; //$NON-NLS-1$
- private static final String PROPERTY_SOURCE_FOLDER =
- "manifestPackageSourceFolder"; //$NON-NLS-1$
-
private static final String PROPERTY_COMPILE_RESOURCES = "compileResources"; //$NON-NLS-1$
-
- static final String PROPERTY_ANDROID_GENERATED = "androidGenerated"; //$NON-NLS-1$
- static final String PROPERTY_ANDROID_CONFLICT = "androidConflict"; //$NON-NLS-1$
+ private static final String PROPERTY_COMPILE_AIDL = "compileAidl"; //$NON-NLS-1$
/**
* Single line aidl error<br>
@@ -83,24 +77,58 @@ public class PreCompilerBuilder extends BaseBuilder {
private static Pattern sAidlPattern1 = Pattern.compile("^(.+?):(\\d+):\\s(.+)$"); //$NON-NLS-1$
/**
- * Compile flag. This is set to true if one of the changed/added/removed
- * file is a resource file. Upon visiting all the delta resources, if
- * this flag is true, then we know we'll have to compile the resources
- * into R.java
+ * Data to temporarly store aidl source file information
+ */
+ static class AidlData {
+ IFile aidlFile;
+ IFolder sourceFolder;
+
+ AidlData(IFolder sourceFolder, IFile aidlFile) {
+ this.sourceFolder = sourceFolder;
+ this.aidlFile = aidlFile;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof AidlData) {
+ AidlData file = (AidlData)obj;
+ return aidlFile.equals(file.aidlFile) && sourceFolder.equals(file.sourceFolder);
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Resource Compile flag. This flag is reset to false after each successful compilation, and
+ * stored in the project persistent properties. This allows the builder to remember its state
+ * when the project is closed/opened.
*/
- private boolean mCompileResources = false;
+ private boolean mMustCompileResources = false;
/** List of .aidl files found that are modified or new. */
- private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+ private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
/** List of .aidl files that have been removed. */
- private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+ private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
/** cache of the java package defined in the manifest */
private String mManifestPackage;
+
+ /** Output folder for generated Java File. Created on the Builder init
+ * @see #startupOnInitialize()
+ */
+ private IFolder mGenFolder;
- /** Source folder containing the java package defined in the manifest. */
- private IFolder mManifestPackageSourceFolder;
+ /**
+ * Progress monitor used at the end of every build to refresh the content of the 'gen' folder
+ * and set the generated files as derived.
+ */
+ private DerivedProgressMonitor mDerivedProgressMonitor;
/**
* Progress monitor waiting the end of the process to set a persistent value
@@ -109,91 +137,36 @@ public class PreCompilerBuilder extends BaseBuilder {
* to be known by eclipse, before we can call <code>resource.setPersistentProperty</code> on
* a new file.
*/
- private static class RefreshProgressMonitor implements IProgressMonitor {
+ private static class DerivedProgressMonitor implements IProgressMonitor {
private boolean mCancelled = false;
- private IFile mNewFile;
- private IFile mSource;
- private boolean mDoneExecuted = false;
- public RefreshProgressMonitor(IFile newFile, IFile source) {
- mNewFile = newFile;
- mSource = source;
- }
-
- public void beginTask(String name, int totalWork) {
- }
-
- public void done() {
- if (mDoneExecuted == false) {
- mDoneExecuted = true;
- if (mNewFile.exists()) {
- ProjectHelper.saveResourceProperty(mNewFile, PROPERTY_ANDROID_GENERATED,
- mSource);
- try {
- mNewFile.setDerived(true);
- } catch (CoreException e) {
- // This really shouldn't happen since we check that the resource exist.
- // Worst case scenario, the resource isn't marked as derived.
- }
- }
- }
- }
-
- public void internalWorked(double work) {
- }
-
- public boolean isCanceled() {
- return mCancelled;
- }
-
- public void setCanceled(boolean value) {
- mCancelled = value;
- }
-
- public void setTaskName(String name) {
+ private final ArrayList<IFile> mFileList = new ArrayList<IFile>();
+ private boolean mDone = false;
+ public DerivedProgressMonitor() {
}
-
- public void subTask(String name) {
- }
-
- public void worked(int work) {
+
+ void addFile(IFile file) {
+ mFileList.add(file);
}
- }
-
- /**
- * Progress Monitor setting up to two files as derived once their parent is refreshed.
- * This is used as ProgressMonitor to refresh the R.java/Manifest.java parent (to display
- * the newly created files in the package explorer).
- */
- private static class DerivedProgressMonitor implements IProgressMonitor {
- private boolean mCancelled = false;
- private IFile mFile1;
- private IFile mFile2;
- private boolean mDoneExecuted = false;
- public DerivedProgressMonitor(IFile file1, IFile file2) {
- mFile1 = file1;
- mFile2 = file2;
+
+ void reset() {
+ mFileList.clear();
+ mDone = false;
}
public void beginTask(String name, int totalWork) {
}
public void done() {
- if (mDoneExecuted == false) {
- if (mFile1 != null && mFile1.exists()) {
- mDoneExecuted = true;
- try {
- mFile1.setDerived(true);
- } catch (CoreException e) {
- // This really shouldn't happen since we check that the resource edit.
- // Worst case scenario, the resource isn't marked as derived.
- }
- }
- if (mFile2 != null && mFile2.exists()) {
- try {
- mFile2.setDerived(true);
- } catch (CoreException e) {
- // This really shouldn't happen since we check that the resource edit.
- // Worst case scenario, the resource isn't marked as derived.
+ if (mDone == false) {
+ mDone = true;
+ for (IFile file : mFileList) {
+ if (file.exists()) {
+ try {
+ file.setDerived(true);
+ } catch (CoreException e) {
+ // This really shouldn't happen since we check that the resource exist.
+ // Worst case scenario, the resource isn't marked as derived.
+ }
}
}
}
@@ -229,322 +202,306 @@ public class PreCompilerBuilder extends BaseBuilder {
@Override
protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
throws CoreException {
- // First thing we do is go through the resource delta to not
- // lose it if we have to abort the build for any reason.
+ try {
+ mDerivedProgressMonitor.reset();
- // get the project objects
- IProject project = getProject();
-
- // Top level check to make sure the build can move forward.
- abortOnBadSetup(project);
-
- IJavaProject javaProject = JavaCore.create(project);
- IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
-
- // now we need to get the classpath list
- ArrayList<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject);
-
- PreCompilerDeltaVisitor dv = null;
- String javaPackage = null;
-
- if (kind == FULL_BUILD) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Start_Full_Pre_Compiler);
- mCompileResources = true;
- buildAidlCompilationList(project, sourceList);
- } else {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Start_Inc_Pre_Compiler);
-
- // Go through the resources and see if something changed.
- // Even if the mCompileResources flag is true from a previously aborted
- // build, we need to go through the Resource delta to get a possible
- // list of aidl files to compile/remove.
- IResourceDelta delta = getDelta(project);
- if (delta == null) {
- mCompileResources = true;
- buildAidlCompilationList(project, sourceList);
+ // First thing we do is go through the resource delta to not
+ // lose it if we have to abort the build for any reason.
+
+ // get the project objects
+ IProject project = getProject();
+
+ // Top level check to make sure the build can move forward.
+ abortOnBadSetup(project);
+
+ IJavaProject javaProject = JavaCore.create(project);
+ IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
+
+ // now we need to get the classpath list
+ ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
+ javaProject);
+
+ PreCompilerDeltaVisitor dv = null;
+ String javaPackage = null;
+
+ if (kind == FULL_BUILD) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Start_Full_Pre_Compiler);
+ mMustCompileResources = true;
+ buildAidlCompilationList(project, sourceFolderPathList);
} else {
- dv = new PreCompilerDeltaVisitor(this, sourceList);
- delta.accept(dv);
-
- // record the state
- mCompileResources |= dv.getCompileResources();
-
- // handle aidl modification
- if (dv.getFullAidlRecompilation()) {
- buildAidlCompilationList(project, sourceList);
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Start_Inc_Pre_Compiler);
+
+ // Go through the resources and see if something changed.
+ // Even if the mCompileResources flag is true from a previously aborted
+ // build, we need to go through the Resource delta to get a possible
+ // list of aidl files to compile/remove.
+ IResourceDelta delta = getDelta(project);
+ if (delta == null) {
+ mMustCompileResources = true;
+ buildAidlCompilationList(project, sourceFolderPathList);
} else {
+ dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList);
+ delta.accept(dv);
+
+ // record the state
+ mMustCompileResources |= dv.getCompileResources();
+
+ // handle aidl modification, and update mMustCompileAidl
mergeAidlFileModifications(dv.getAidlToCompile(),
dv.getAidlToRemove());
+
+ // get the java package from the visitor
+ javaPackage = dv.getManifestPackage();
}
-
- // get the java package from the visitor
- javaPackage = dv.getManifestPackage();
}
- }
-
- // store the build status in the persistent storage
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mCompileResources);
- // TODO also needs to store the list of aidl to compile/remove
-
- // if there was some XML errors, we just return w/o doing
- // anything since we've put some markers in the files anyway.
- if (dv != null && dv.mXmlError) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Xml_Error);
-
- // This interrupts the build. The next builders will not run.
- stopBuild(Messages.Xml_Error);
- }
-
-
- // get the manifest file
- IFile manifest = AndroidManifestHelper.getManifest(project);
-
- if (manifest == null) {
- String msg = String.format(Messages.s_File_Missing,
- AndroidConstants.FN_ANDROID_MANIFEST);
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- // This interrupts the build. The next builders will not run.
- stopBuild(msg);
- }
-
- // lets check the XML of the manifest first, if that hasn't been done by the
- // resource delta visitor yet.
- if (dv == null || dv.getCheckedManifestXml() == false) {
- BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
- AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(manifest,
- errorListener);
-
- if (errorListener.mHasXmlError == true) {
- // there was an error in the manifest, its file has been marked,
- // by the XmlErrorHandler.
- // We return;
- String msg = String.format(Messages.s_Contains_Xml_Error,
+
+ // store the build status in the persistent storage
+ saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
+
+ // if there was some XML errors, we just return w/o doing
+ // anything since we've put some markers in the files anyway.
+ if (dv != null && dv.mXmlError) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Xml_Error);
+
+ // This interrupts the build. The next builders will not run.
+ stopBuild(Messages.Xml_Error);
+ }
+
+
+ // get the manifest file
+ IFile manifest = AndroidManifestHelper.getManifest(project);
+
+ if (manifest == null) {
+ String msg = String.format(Messages.s_File_Missing,
AndroidConstants.FN_ANDROID_MANIFEST);
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
-
+ markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+
// This interrupts the build. The next builders will not run.
stopBuild(msg);
}
-
- // get the java package from the parser
- javaPackage = parser.getPackage();
- }
-
- if (javaPackage == null || javaPackage.length() == 0) {
- // looks like the AndroidManifest file isn't valid.
- String msg = String.format(Messages.s_Doesnt_Declare_Package_Error,
- AndroidConstants.FN_ANDROID_MANIFEST);
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- msg);
-
- // This interrupts the build. The next builders will not run.
- stopBuild(msg);
- }
-
- // at this point we have the java package. We need to make sure it's not a different package
- // than the previous one that were built.
- if (javaPackage.equals(mManifestPackage) == false) {
- // The manifest package has changed, the user may want to update
- // the launch configuration
- if (mManifestPackage != null) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Checking_Package_Change);
-
- FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage, javaPackage);
- flc.start();
+
+ // lets check the XML of the manifest first, if that hasn't been done by the
+ // resource delta visitor yet.
+ if (dv == null || dv.getCheckedManifestXml() == false) {
+ BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
+ AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(manifest,
+ errorListener);
+
+ if (errorListener.mHasXmlError == true) {
+ // there was an error in the manifest, its file has been marked,
+ // by the XmlErrorHandler.
+ // We return;
+ String msg = String.format(Messages.s_Contains_Xml_Error,
+ AndroidConstants.FN_ANDROID_MANIFEST);
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
+
+ // This interrupts the build. The next builders will not run.
+ stopBuild(msg);
+ }
+
+ // get the java package from the parser
+ javaPackage = parser.getPackage();
}
-
- // now we delete the generated classes from their previous location
- deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
- mManifestPackageSourceFolder, mManifestPackage);
- deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
- mManifestPackageSourceFolder, mManifestPackage);
-
- // record the new manifest package, and save it.
- mManifestPackage = javaPackage;
- saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
- }
-
- if (mCompileResources) {
- // we need to figure out where to store the R class.
- // get the parent folder for R.java and update mManifestPackageSourceFolder
- IFolder packageFolder = getManifestPackageFolder(project, sourceList);
-
- // at this point, either we have found the package or not.
- // if we haven't well it's time to tell the user and abort
- if (mManifestPackageSourceFolder == null) {
- // mark the manifest file
- String message = String.format(Messages.Package_s_Doesnt_Exist_Error,
- mManifestPackage);
- BaseProjectHelper.addMarker(manifest, AndroidConstants.MARKER_AAPT_COMPILE, message,
- IMarker.SEVERITY_ERROR);
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, message);
-
- // abort
+
+ if (javaPackage == null || javaPackage.length() == 0) {
+ // looks like the AndroidManifest file isn't valid.
+ String msg = String.format(Messages.s_Doesnt_Declare_Package_Error,
+ AndroidConstants.FN_ANDROID_MANIFEST);
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ msg);
+
// This interrupts the build. The next builders will not run.
- stopBuild(message);
+ stopBuild(msg);
}
-
-
- // found the folder in which to write the stuff
-
- // get the resource folder
- IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
-
- // get the file system path
- IPath outputLocation = mManifestPackageSourceFolder.getLocation();
- IPath resLocation = resFolder.getLocation();
- IPath manifestLocation = manifest.getLocation();
-
- // those locations have to exist for us to do something!
- if (outputLocation != null && resLocation != null
- && manifestLocation != null) {
- String osOutputPath = outputLocation.toOSString();
- String osResPath = resLocation.toOSString();
- String osManifestPath = manifestLocation.toOSString();
-
- // remove the aapt markers
- removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT_COMPILE);
- removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT_COMPILE);
-
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Preparing_Generated_Files);
-
- // since the R.java file may be already existing in read-only
- // mode we need to make it readable so that aapt can overwrite
- // it
- IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
- prepareFileForExternalModification(rJavaFile);
-
- // do the same for the Manifest.java class
- IFile manifestJavaFile = packageFolder.getFile(AndroidConstants.FN_MANIFEST_CLASS);
- prepareFileForExternalModification(manifestJavaFile);
-
- // we actually need to delete the manifest.java as it may become empty and in this
- // case aapt doesn't generate an empty one, but instead doesn't touch it.
- manifestJavaFile.delete(true, null);
-
- // launch aapt: create the command line
- ArrayList<String> array = new ArrayList<String>();
- array.add(projectTarget.getPath(IAndroidTarget.AAPT));
- array.add("package"); //$NON-NLS-1$
- array.add("-m"); //$NON-NLS-1$
- if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
- array.add("-v"); //$NON-NLS-1$
+
+ // at this point we have the java package. We need to make sure it's not a different
+ // package than the previous one that were built.
+ if (javaPackage.equals(mManifestPackage) == false) {
+ // The manifest package has changed, the user may want to update
+ // the launch configuration
+ if (mManifestPackage != null) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Checking_Package_Change);
+
+ FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage,
+ javaPackage);
+ flc.start();
}
- array.add("-J"); //$NON-NLS-1$
- array.add(osOutputPath);
- array.add("-M"); //$NON-NLS-1$
- array.add(osManifestPath);
- array.add("-S"); //$NON-NLS-1$
- array.add(osResPath);
- array.add("-I"); //$NON-NLS-1$
- array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
-
- if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
- StringBuilder sb = new StringBuilder();
- for (String c : array) {
- sb.append(c);
- sb.append(' ');
+
+ // now we delete the generated classes from their previous location
+ deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
+ mManifestPackage);
+ deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
+ mManifestPackage);
+
+ // record the new manifest package, and save it.
+ mManifestPackage = javaPackage;
+ saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
+ }
+
+ if (mMustCompileResources) {
+ // we need to figure out where to store the R class.
+ // get the parent folder for R.java and update mManifestPackageSourceFolder
+ IFolder packageFolder = getGenManifestPackageFolder(project);
+
+ // get the resource folder
+ IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
+
+ // get the file system path
+ IPath outputLocation = mGenFolder.getLocation();
+ IPath resLocation = resFolder.getLocation();
+ IPath manifestLocation = manifest.getLocation();
+
+ // those locations have to exist for us to do something!
+ if (outputLocation != null && resLocation != null
+ && manifestLocation != null) {
+ String osOutputPath = outputLocation.toOSString();
+ String osResPath = resLocation.toOSString();
+ String osManifestPath = manifestLocation.toOSString();
+
+ // remove the aapt markers
+ removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT_COMPILE);
+ removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT_COMPILE);
+
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Preparing_Generated_Files);
+
+ // since the R.java file may be already existing in read-only
+ // mode we need to make it readable so that aapt can overwrite
+ // it
+ IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
+
+ // do the same for the Manifest.java class
+ IFile manifestJavaFile = packageFolder.getFile(
+ AndroidConstants.FN_MANIFEST_CLASS);
+
+ // we actually need to delete the manifest.java as it may become empty and
+ // in this case aapt doesn't generate an empty one, but instead doesn't
+ // touch it.
+ manifestJavaFile.delete(true, null);
+
+ // launch aapt: create the command line
+ ArrayList<String> array = new ArrayList<String>();
+ array.add(projectTarget.getPath(IAndroidTarget.AAPT));
+ array.add("package"); //$NON-NLS-1$
+ array.add("-m"); //$NON-NLS-1$
+ if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
+ array.add("-v"); //$NON-NLS-1$
}
- String cmd_line = sb.toString();
- AdtPlugin.printToConsole(project, cmd_line);
- }
-
- // launch
- int execError = 1;
- try {
- // launch the command line process
- Process process = Runtime.getRuntime().exec(
- array.toArray(new String[array.size()]));
-
- // list to store each line of stderr
- ArrayList<String> results = new ArrayList<String>();
-
- // get the output and return code from the process
- execError = grabProcessOutput(process, results);
-
- // attempt to parse the error output
- boolean parsingError = parseAaptOutput(results, project);
-
- // if we couldn't parse the output we display it in the console.
- if (parsingError) {
- if (execError != 0) {
- AdtPlugin.printErrorToConsole(project, results.toArray());
- } else {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_NORMAL,
- project, results.toArray());
+ array.add("-J"); //$NON-NLS-1$
+ array.add(osOutputPath);
+ array.add("-M"); //$NON-NLS-1$
+ array.add(osManifestPath);
+ array.add("-S"); //$NON-NLS-1$
+ array.add(osResPath);
+ array.add("-I"); //$NON-NLS-1$
+ array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
+
+ if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
+ StringBuilder sb = new StringBuilder();
+ for (String c : array) {
+ sb.append(c);
+ sb.append(' ');
}
+ String cmd_line = sb.toString();
+ AdtPlugin.printToConsole(project, cmd_line);
}
-
- if (execError != 0) {
- // if the exec failed, and we couldn't parse the error output (and therefore
- // not all files that should have been marked, were marked), we put a
- // generic marker on the project and abort.
+
+ // launch
+ int execError = 1;
+ try {
+ // launch the command line process
+ Process process = Runtime.getRuntime().exec(
+ array.toArray(new String[array.size()]));
+
+ // list to store each line of stderr
+ ArrayList<String> results = new ArrayList<String>();
+
+ // get the output and return code from the process
+ execError = grabProcessOutput(process, results);
+
+ // attempt to parse the error output
+ boolean parsingError = parseAaptOutput(results, project);
+
+ // if we couldn't parse the output we display it in the console.
if (parsingError) {
- markProject(AdtConstants.MARKER_ADT, Messages.Unparsed_AAPT_Errors,
- IMarker.SEVERITY_ERROR);
+ if (execError != 0) {
+ AdtPlugin.printErrorToConsole(project, results.toArray());
+ } else {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_NORMAL,
+ project, results.toArray());
+ }
}
-
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.AAPT_Error);
-
- // abort if exec failed.
+
+ if (execError != 0) {
+ // if the exec failed, and we couldn't parse the error output
+ // (and therefore not all files that should have been marked,
+ // were marked), we put a generic marker on the project and abort.
+ if (parsingError) {
+ markProject(AdtConstants.MARKER_ADT, Messages.Unparsed_AAPT_Errors,
+ IMarker.SEVERITY_ERROR);
+ }
+
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.AAPT_Error);
+
+ // abort if exec failed.
+ // This interrupts the build. The next builders will not run.
+ stopBuild(Messages.AAPT_Error);
+ }
+ } catch (IOException e1) {
+ // something happen while executing the process,
+ // mark the project and exit
+ String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
+ markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+
// This interrupts the build. The next builders will not run.
- stopBuild(Messages.AAPT_Error);
+ stopBuild(msg);
+ } catch (InterruptedException e) {
+ // we got interrupted waiting for the process to end...
+ // mark the project and exit
+ String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
+ markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+
+ // This interrupts the build. The next builders will not run.
+ stopBuild(msg);
+ }
+
+ // if the return code was OK, we refresh the folder that
+ // contains R.java to force a java recompile.
+ if (execError == 0) {
+ // now add the R.java/Manifest.java to the list of file to be marked
+ // as derived.
+ mDerivedProgressMonitor.addFile(rJavaFile);
+ mDerivedProgressMonitor.addFile(manifestJavaFile);
+
+ // build has been done. reset the state of the builder
+ mMustCompileResources = false;
+
+ // and store it
+ saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES,
+ mMustCompileResources);
}
- } catch (IOException e1) {
- // something happen while executing the process,
- // mark the project and exit
- String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- // This interrupts the build. The next builders will not run.
- stopBuild(msg);
- } catch (InterruptedException e) {
- // we got interrupted waiting for the process to end...
- // mark the project and exit
- String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- // This interrupts the build. The next builders will not run.
- stopBuild(msg);
- }
-
- // if the return code was OK, we refresh the folder that
- // contains R.java to force a java recompile.
- if (execError == 0) {
- // now set the R.java/Manifest.java file as read only.
- finishJavaFilesAfterExternalModification(rJavaFile, manifestJavaFile);
-
- // build has been done. reset the state of the builder
- mCompileResources = false;
-
- // and store it
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mCompileResources);
}
+ } else {
+ // nothing to do
}
- } else {
- // nothing to do
- }
-
- // now handle the aidl stuff.
- // look for a preprocessed aidl file
- IResource projectAidl = project.findMember("project.aidl"); //$NON-NLS-1$
- String folderAidlPath = null;
- if (projectAidl != null && projectAidl.exists()) {
- folderAidlPath = projectAidl.getLocation().toOSString();
- }
- boolean aidlStatus = handleAidl(projectTarget, sourceList, folderAidlPath, monitor);
-
- if (aidlStatus == false && mCompileResources == false) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.Nothing_To_Compile);
+
+ // now handle the aidl stuff.
+ boolean aidlStatus = handleAidl(projectTarget, sourceFolderPathList, monitor);
+
+ if (aidlStatus == false && mMustCompileResources == false) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ Messages.Nothing_To_Compile);
+ }
+ } finally {
+ // refresh the 'gen' source folder. Once this is done with the custom progress
+ // monitor to mark all new files as derived
+ mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
}
return null;
@@ -557,67 +514,57 @@ public class PreCompilerBuilder extends BaseBuilder {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(),
Messages.Removing_Generated_Classes);
- // check if we have the R.java info already.
- if (mManifestPackageSourceFolder != null && mManifestPackage != null) {
- deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
- mManifestPackageSourceFolder, mManifestPackage);
- deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
- mManifestPackageSourceFolder, mManifestPackage);
- }
-
- // FIXME: delete all java generated from aidl.
+ // remove all the derived resources from the 'gen' source folder.
+ removeDerivedResources(mGenFolder, monitor);
}
@Override
protected void startupOnInitialize() {
super.startupOnInitialize();
+
+ mDerivedProgressMonitor = new DerivedProgressMonitor();
+
+ IProject project = getProject();
// load the previous IFolder and java package.
mManifestPackage = loadProjectStringProperty(PROPERTY_PACKAGE);
- IResource resource = loadProjectResourceProperty(PROPERTY_SOURCE_FOLDER);
- if (resource instanceof IFolder) {
- mManifestPackageSourceFolder = (IFolder)resource;
- }
+
+ // get the source folder in which all the Java files are created
+ mGenFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
- // Load the current compile flag. We ask for true if not found to force a
+ // Load the current compile flags. We ask for true if not found to force a
// recompile.
- mCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
+ mMustCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
+ boolean mustCompileAidl = loadProjectBooleanProperty(PROPERTY_COMPILE_AIDL, true);
+
+ // if we stored that we have to compile some aidl, we build the list that will compile them
+ // all
+ if (mustCompileAidl) {
+ IJavaProject javaProject = JavaCore.create(project);
+ ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
+ javaProject);
+
+ buildAidlCompilationList(project, sourceFolderPathList);
+ }
}
/**
* Delete the a generated java class associated with the specified java package.
* @param filename Name of the generated file to remove.
- * @param sourceFolder The source Folder containing the old java package.
* @param javaPackage the old java package
*/
- private void deleteObsoleteGeneratedClass(String filename, IFolder sourceFolder,
- String javaPackage) {
- if (sourceFolder == null || javaPackage == null) {
+ private void deleteObsoleteGeneratedClass(String filename, String javaPackage) {
+ if (javaPackage == null) {
return;
}
-
- // convert the java package into path
- String[] segments = javaPackage.split(AndroidConstants.RE_DOT);
-
- StringBuilder path = new StringBuilder();
- for (String s : segments) {
- path.append(AndroidConstants.WS_SEP_CHAR);
- path.append(s);
- }
-
- // appends the name of the generated file
- path.append(AndroidConstants.WS_SEP_CHAR);
- path.append(filename);
-
- Path iPath = new Path(path.toString());
+
+ IPath packagePath = getJavaPackagePath(javaPackage);
+ IPath iPath = packagePath.append(filename);
// Find a matching resource object.
- IResource javaFile = sourceFolder.findMember(iPath);
+ IResource javaFile = mGenFolder.findMember(iPath);
if (javaFile != null && javaFile.exists() && javaFile.getType() == IResource.FILE) {
try {
- // remove the read-only tag
- prepareFileForExternalModification((IFile)javaFile);
-
// delete
javaFile.delete(true, null);
@@ -626,7 +573,8 @@ public class PreCompilerBuilder extends BaseBuilder {
} catch (CoreException e) {
// failed to delete it, the user will have to delete it manually.
- String message = String.format(Messages.Delete_Obsolete_Error, path);
+ String message = String.format(Messages.Delete_Obsolete_Error,
+ javaFile.getFullPath());
IProject project = getProject();
AdtPlugin.printErrorToConsole(project, message);
AdtPlugin.printErrorToConsole(project, e.getMessage());
@@ -635,94 +583,38 @@ public class PreCompilerBuilder extends BaseBuilder {
}
/**
- * Looks for the folder containing the package defined in the manifest. It looks in the
- * list of source folders for the one containing folders matching the package defined in the
- * manifest (from the field <code>mManifestPackage</code>). It returns the final folder, which
- * will contain the R class, and update the field <code>mManifestPackageSourceFolder</code>
- * to be the source folder containing the full package.
+ * Creates a relative {@link IPath} from a java package.
+ * @param javaPackageName the java package.
+ */
+ private IPath getJavaPackagePath(String javaPackageName) {
+ // convert the java package into path
+ String[] segments = javaPackageName.split(AndroidConstants.RE_DOT);
+
+ StringBuilder path = new StringBuilder();
+ for (String s : segments) {
+ path.append(AndroidConstants.WS_SEP_CHAR);
+ path.append(s);
+ }
+
+ return new Path(path.toString());
+ }
+
+ /**
+ * Returns an {@link IFolder} (located inside the 'gen' source folder), that matches the
+ * package defined in the manifest. This {@link IFolder} may not actually exist
+ * (aapt will create it anyway).
* @param project The project.
- * @param sourceList The list of source folders for the project.
- * @return the package that will contain the R class or null if the folder was not found.
+ * @return the {@link IFolder} that will contain the R class or null if the folder was not found.
* @throws CoreException
*/
- private IFolder getManifestPackageFolder(IProject project, ArrayList<IPath> sourceList)
+ private IFolder getGenManifestPackageFolder(IProject project)
throws CoreException {
- // split the package in segments
- String[] packageSegments = mManifestPackage.split(AndroidConstants.RE_DOT);
-
- // we look for 2 folders.
- // 1. The source folder that contains the full java package.
- // we will store the folder in the field mJavaSourceFolder, for reuse during
- IFolder manifestPackageSourceFolder = null;
- // subsequent builds. This is the folder we will give to aapt.
- // 2. The folder actually containing the R.java files. We need this one to do a refresh
- IFolder packageFolder = null;
-
- for (IPath iPath : sourceList) {
- int packageSegmentIndex = 0;
-
- // the path is relative to the workspace. We ignore the first segment,
- // when getting the resource from the IProject object.
- IResource classpathEntry = project.getFolder(iPath.removeFirstSegments(1));
-
- if (classpathEntry instanceof IFolder) {
- IFolder classpathFolder = (IFolder)classpathEntry;
- IFolder folder = classpathFolder;
-
- boolean failed = false;
- while (failed == false
- && packageSegmentIndex < packageSegments.length) {
-
- // loop on that folder content looking for folders
- // that match the package
- // defined in AndroidManifest.xml
-
- // get the folder content
- IResource[] content = folder.members();
-
- // this is the segment we look for
- String segment = packageSegments[packageSegmentIndex];
-
- // did we find it at this level
- boolean found = false;
-
- for (IResource r : content) {
- // look for the java package segment
- if (r instanceof IFolder) {
- if (r.getName().equals(segment)) {
- // we need to skip to the next one
- folder = (IFolder)r;
- packageSegmentIndex++;
- found = true;
- break;
- }
- }
- }
-
- // if we didn't find it at this level we just fail.
- if (found == false) {
- failed = true;
- }
- }
-
- // if we didn't fail then we found it. no point in
- // looping through the rest
- // or the classpathEntry
- if (failed == false) {
- // save the target folder reference
- manifestPackageSourceFolder = classpathFolder;
- packageFolder = folder;
- break;
- }
- }
- }
-
- // save the location of the folder into the persistent storage
- if (manifestPackageSourceFolder != mManifestPackageSourceFolder) {
- mManifestPackageSourceFolder = manifestPackageSourceFolder;
- saveProjectResourceProperty(PROPERTY_SOURCE_FOLDER, mManifestPackageSourceFolder);
- }
- return packageFolder;
+ // get the path for the package
+ IPath packagePath = getJavaPackagePath(mManifestPackage);
+
+ // get a folder for this path under the 'gen' source folder, and return it.
+ // This IFolder may not reference an actual existing folder.
+ return mGenFolder.getFolder(packagePath);
}
/**
@@ -730,27 +622,22 @@ public class PreCompilerBuilder extends BaseBuilder {
* created from aidl files that are now gone.
* @param projectTarget Target of the project
* @param sourceFolders the list of source folders, relative to the workspace.
- * @param folderAidlPath
* @param monitor the projess monitor
* @returns true if it did something
* @throws CoreException
*/
private boolean handleAidl(IAndroidTarget projectTarget, ArrayList<IPath> sourceFolders,
- String folderAidlPath, IProgressMonitor monitor) throws CoreException {
+ IProgressMonitor monitor) throws CoreException {
if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
return false;
}
-
// create the command line
- String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)];
+ String[] command = new String[4 + sourceFolders.size()];
int index = 0;
- int aidlIndex;
command[index++] = projectTarget.getPath(IAndroidTarget.AIDL);
- command[aidlIndex = index++] = "-p"; //$NON-NLS-1$
- if (folderAidlPath != null) {
- command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$
- }
+ command[index++] = "-p" + Sdk.getCurrent().getTarget(getProject()).getPath( //$NON-NLS-1$
+ IAndroidTarget.ANDROID_AIDL);
// since the path are relative to the workspace and not the project itself, we need
// the workspace root.
@@ -761,81 +648,44 @@ public class PreCompilerBuilder extends BaseBuilder {
}
// list of files that have failed compilation.
- ArrayList<IFile> stillNeedCompilation = new ArrayList<IFile>();
+ ArrayList<AidlData> stillNeedCompilation = new ArrayList<AidlData>();
// if an aidl file is being removed before we managed to compile it, it'll be in
// both list. We *need* to remove it from the compile list or it'll never go away.
- for (IFile aidlFile : mAidlToRemove) {
+ for (AidlData aidlFile : mAidlToRemove) {
int pos = mAidlToCompile.indexOf(aidlFile);
if (pos != -1) {
mAidlToCompile.remove(pos);
}
}
-
+
// loop until we've compile them all
- for (IFile aidlFile : mAidlToCompile) {
+ for (AidlData aidlData : mAidlToCompile) {
// Remove the AIDL error markers from the aidl file
- removeMarkersFromFile(aidlFile, AndroidConstants.MARKER_AIDL);
-
- // get the path
- IPath iPath = aidlFile.getLocation();
- String osPath = iPath.toOSString();
-
- // get the parent container
- IContainer parentContainer = aidlFile.getParent();
-
- // replace the extension in both the full path and the
- // last segment
- String osJavaPath = osPath.replaceAll(AndroidConstants.RE_AIDL_EXT,
- AndroidConstants.DOT_JAVA);
- String javaName = aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
- AndroidConstants.DOT_JAVA);
-
- // check if we can compile it, or if there is a conflict with a java file
- boolean conflict = ProjectHelper.loadBooleanProperty(aidlFile,
- PROPERTY_ANDROID_CONFLICT, false);
- if (conflict) {
- String msg = String.format(Messages.AIDL_Java_Conflict, javaName,
- aidlFile.getName());
-
- // put a marker
- BaseProjectHelper.addMarker(aidlFile, AndroidConstants.MARKER_AIDL, msg,
- IMarker.SEVERITY_ERROR);
-
- // output an error
- AdtPlugin.printErrorToConsole(getProject(), msg);
-
- stillNeedCompilation.add(aidlFile);
+ removeMarkersFromFile(aidlData.aidlFile, AndroidConstants.MARKER_AIDL);
- // move on to next file
- continue;
- }
-
- // get the resource for the java file.
- Path javaIPath = new Path(javaName);
- IFile javaFile = parentContainer.getFile(javaIPath);
-
- // if the file was read-only, this will make it readable.
- prepareFileForExternalModification(javaFile);
+ // get the path of the source file.
+ IPath sourcePath = aidlData.aidlFile.getLocation();
+ String osSourcePath = sourcePath.toOSString();
+
+ IFile javaFile = getGenDestinationFile(aidlData, true /*createFolders*/, monitor);
// finish to set the command line.
- command[aidlIndex] = "-p" + Sdk.getCurrent().getTarget(aidlFile.getProject()).getPath(
- IAndroidTarget.ANDROID_AIDL); //$NON-NLS-1$
- command[index] = osPath;
- command[index + 1] = osJavaPath;
+ command[index] = osSourcePath;
+ command[index + 1] = javaFile.getLocation().toOSString();
// launch the process
- if (execAidl(command, aidlFile) == false) {
+ if (execAidl(command, aidlData.aidlFile) == false) {
// aidl failed. File should be marked. We add the file to the list
// of file that will need compilation again.
- stillNeedCompilation.add(aidlFile);
+ stillNeedCompilation.add(aidlData);
// and we move on to the next one.
continue;
} else {
- // since the exec worked, we refresh the parent, and set the
- // file as read only.
- finishFileAfterExternalModification(javaFile, aidlFile);
+ // make sure the file will be marked as derived once we refresh the 'gen' source
+ // folder.
+ mDerivedProgressMonitor.addFile(javaFile);
}
}
@@ -844,44 +694,68 @@ public class PreCompilerBuilder extends BaseBuilder {
mAidlToCompile.addAll(stillNeedCompilation);
// Remove the java files created from aidl files that have been removed.
- for (IFile aidlFile : mAidlToRemove) {
- // make the java filename
- String javaName = aidlFile.getName().replaceAll(
- AndroidConstants.RE_AIDL_EXT,
- AndroidConstants.DOT_JAVA);
-
- // get the parent container
- IContainer ic = aidlFile.getParent();
-
- // and get the IFile corresponding to the java file.
- IFile javaFile = ic.getFile(new Path(javaName));
- if (javaFile != null && javaFile.exists() ) {
- // check if this java file has a persistent data marking it as generated by
- // the builder.
- // While we put the aidl path as a resource, internally it's all string anyway.
- // We use loadStringProperty, because loadResourceProperty tries to match
- // the string value (a path in this case) with an existing resource, but
- // the aidl file was deleted, so it would return null, even though the property
- // existed.
- String aidlPath = ProjectHelper.loadStringProperty(javaFile,
- PROPERTY_ANDROID_GENERATED);
-
- if (aidlPath != null) {
- // This confirms the java file was generated by the builder,
- // we can delete the aidlFile.
- javaFile.delete(true, null);
-
- // Refresh parent.
- ic.refreshLocal(IResource.DEPTH_ONE, monitor);
- }
+ for (AidlData aidlData : mAidlToRemove) {
+ IFile javaFile = getGenDestinationFile(aidlData, false /*createFolders*/, monitor);
+ if (javaFile.exists()) {
+ // This confirms the java file was generated by the builder,
+ // we can delete the aidlFile.
+ javaFile.delete(true, null);
+
+ // Refresh parent.
+ javaFile.getParent().refreshLocal(IResource.DEPTH_ONE, monitor);
}
}
+
mAidlToRemove.clear();
+ // store the build state. If there are any files that failed to compile, we will
+ // force a full aidl compile on the next project open. (unless a full compilation succeed
+ // before the project is closed/re-opened.)
+ // TODO: Optimize by saving only the files that need compilation
+ saveProjectBooleanProperty(PROPERTY_COMPILE_AIDL , mAidlToCompile.size() > 0);
+
return true;
}
/**
+ * Returns the {@link IFile} handle to the destination file for a given aild source file
+ * ({@link AidlData}).
+ * @param aidlData the data for the aidl source file.
+ * @param createFolders whether or not the parent folder of the destination should be created
+ * if it does not exist.
+ * @param monitor the progress monitor
+ * @return the handle to the destination file.
+ * @throws CoreException
+ */
+ private IFile getGenDestinationFile(AidlData aidlData, boolean createFolders,
+ IProgressMonitor monitor) throws CoreException {
+ // build the destination folder path.
+ // Use the path of the source file, except for the path leading to its source folder,
+ // and for the last segment which is the filename.
+ int segmentToSourceFolderCount = aidlData.sourceFolder.getFullPath().segmentCount();
+ IPath packagePath = aidlData.aidlFile.getFullPath().removeFirstSegments(
+ segmentToSourceFolderCount).removeLastSegments(1);
+ Path destinationPath = new Path(packagePath.toString());
+
+ // get an IFolder for this path. It's relative to the 'gen' folder already
+ IFolder destinationFolder = mGenFolder.getFolder(destinationPath);
+
+ // create it if needed
+ if (destinationFolder.exists() == false && createFolders) {
+ destinationFolder.create(true /*force*/, true /*local*/,
+ new SubProgressMonitor(monitor, 10));;
+ }
+
+ // Build the Java file name from the aidl name.
+ String javaName = aidlData.aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
+ AndroidConstants.DOT_JAVA);
+
+ // get the resource for the java file.
+ IFile javaFile = destinationFolder.getFile(javaName);
+ return javaFile;
+ }
+
+ /**
* Execute the aidl command line, parse the output, and mark the aidl file
* with any reported errors.
* @param command the String array containing the command line to execute.
@@ -933,43 +807,28 @@ public class PreCompilerBuilder extends BaseBuilder {
* Goes through the build paths and fills the list of aidl files to compile
* ({@link #mAidlToCompile}).
* @param project The project.
- * @param buildPaths The list of build paths.
+ * @param sourceFolderPathList The list of source folder paths.
*/
private void buildAidlCompilationList(IProject project,
- ArrayList<IPath> buildPaths) {
- for (IPath p : buildPaths) {
- // Because the path contains the name of the project as well, we
- // need to remove it, to access the final folder.
- String[] segments = p.segments();
- IContainer folder = project;
- for (int i = 1; i < segments.length; i++) {
- IResource r = folder.findMember(segments[i]);
- if (r != null && r.exists() &&
- r.getType() == IResource.FOLDER) {
- folder = (IContainer)r;
- } else {
- // hmm looks like the build path is corrupted/wrong.
- // reset and break
- folder = project;
- break;
- }
- }
-
- // did we ge a folder?
- if (folder != project) {
- // then we scan!
- scanContainerForAidl(folder);
+ ArrayList<IPath> sourceFolderPathList) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ for (IPath sourceFolderPath : sourceFolderPathList) {
+ IFolder sourceFolder = root.getFolder(sourceFolderPath);
+ // we don't look in the 'gen' source folder as there will be no source in there.
+ if (sourceFolder.exists() && sourceFolder.equals(mGenFolder) == false) {
+ scanFolderForAidl(sourceFolder, sourceFolder);
}
}
}
/**
- * Scans a container and fills the list of aidl files to compile.
- * @param container The container to scan.
+ * Scans a folder and fills the list of aidl files to compile.
+ * @param sourceFolder the root source folder.
+ * @param container The folder to scan.
*/
- private void scanContainerForAidl(IContainer container) {
+ private void scanFolderForAidl(IFolder sourceFolder, IFolder folder) {
try {
- IResource[] members = container.members();
+ IResource[] members = folder.members();
for (IResource r : members) {
// get the type of the resource
switch (r.getType()) {
@@ -978,12 +837,12 @@ public class PreCompilerBuilder extends BaseBuilder {
// and that it's an aidl file
if (r.exists() &&
AndroidConstants.EXT_AIDL.equalsIgnoreCase(r.getFileExtension())) {
- mAidlToCompile.add((IFile)r);
+ mAidlToCompile.add(new AidlData(sourceFolder, (IFile)r));
}
break;
case IResource.FOLDER:
// recursively go through children
- scanContainerForAidl((IFolder)r);
+ scanFolderForAidl(sourceFolder, (IFolder)r);
break;
default:
// this would mean it's a project or the workspace root
@@ -1051,13 +910,12 @@ public class PreCompilerBuilder extends BaseBuilder {
* @param toCompile List of file to compile
* @param toRemove List of file to remove
*/
- private void mergeAidlFileModifications(ArrayList<IFile> toCompile,
- ArrayList<IFile> toRemove) {
-
+ private void mergeAidlFileModifications(ArrayList<AidlData> toCompile,
+ ArrayList<AidlData> toRemove) {
// loop through the new toRemove list, and add it to the old one,
// plus remove any file that was still to compile and that are now
// removed
- for (IFile r : toRemove) {
+ for (AidlData r : toRemove) {
if (mAidlToRemove.indexOf(r) == -1) {
mAidlToRemove.add(r);
}
@@ -1072,7 +930,7 @@ public class PreCompilerBuilder extends BaseBuilder {
// Also look for them in the remove list, this would mean that they
// were removed, then added back, and we shouldn't remove them, just
// recompile them.
- for (IFile r : toCompile) {
+ for (AidlData r : toCompile) {
if (mAidlToCompile.indexOf(r) == -1) {
mAidlToCompile.add(r);
}
@@ -1083,68 +941,4 @@ public class PreCompilerBuilder extends BaseBuilder {
}
}
}
-
- /**
- * Prepare an already existing file for modification. File generated from
- * command line processed are marked as read-only. This method prepares
- * them (mark them as read-write) before the command line process is
- * started. A check is made to be sure the file exists.
- * @param file The IResource object for the file to prepare.
- * @throws CoreException
- */
- private void prepareFileForExternalModification(IFile file)
- throws CoreException {
- // file may not exist yet, so we check that.
- if (file != null && file.exists()) {
- // get the attributes.
- ResourceAttributes ra = file.getResourceAttributes();
- if (ra != null) {
- // change the attributes
- ra.setReadOnly(false);
-
- // set the new attributes in the file.
- file.setResourceAttributes(ra);
- }
- }
- }
-
- /**
- * Finish a file created/modified by an outside command line process.
- * The file is marked as modified by Android, and the parent folder is refreshed, so that,
- * in case the file didn't exist beforehand, the file appears in the package explorer.
- * @param rFile The R file to "finish".
- * @param manifestFile The manifest file to "finish".
- * @throws CoreException
- */
- private void finishJavaFilesAfterExternalModification(IFile rFile, IFile manifestFile)
- throws CoreException {
- IContainer parent = rFile.getParent();
-
- IProgressMonitor monitor = new DerivedProgressMonitor(rFile, manifestFile);
-
- // refresh the parent node in the package explorer. Once this is done the custom progress
- // monitor will mark them as derived.
- parent.refreshLocal(IResource.DEPTH_ONE, monitor);
- }
-
- /**
- * Finish a file created/modified by an outside command line process.
- * The file is marked as modified by Android, and the parent folder is refreshed, so that,
- * in case the file didn't exist beforehand, the file appears in the package explorer.
- * @param file The file to "finish".
- * @param aidlFile The AIDL file to "finish".
- * @throws CoreException
- */
- private void finishFileAfterExternalModification(IFile file, IFile aidlFile)
- throws CoreException {
- IContainer parent = file.getParent();
-
- // we need to add a link to the aidl file.
- // We need to wait for the refresh of the parent to be done, so we'll do
- // it in the monitor. This will also set the file as derived.
- IProgressMonitor monitor = new RefreshProgressMonitor(file, aidlFile);
-
- // refresh the parent node in the package explorer.
- parent.refreshLocal(IResource.DEPTH_ONE, monitor);
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
index f4778d7..6841830 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
@@ -19,7 +19,7 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.build.BaseBuilder.BaseDeltaVisitor;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.build.PreCompilerBuilder.AidlData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
@@ -31,14 +31,25 @@ import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
import java.util.ArrayList;
/**
* Resource Delta visitor for the pre-compiler.
+ * <p/>This delta visitor only cares about files that are the source or the result of actions of the
+ * {@link PreCompilerBuilder}:
+ * <ul><li>R.java/Manifest.java generated by compiling the resources</li>
+ * <li>Any Java files generated by <code>aidl</code></li></ul>.
+ *
+ * Therefore it looks for the following:
+ * <ul><li>Any modification in the resource folder</li>
+ * <li>Removed files from the source folder receiving generated Java files</li>
+ * <li>Any modification to aidl files.</li>
+ *
*/
class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
IResourceDeltaVisitor {
@@ -53,14 +64,11 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
private boolean mCompileResources = false;
/** List of .aidl files found that are modified or new. */
- private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+ private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
/** List of .aidl files that have been removed. */
- private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+ private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
- /** Aidl forced recompilation flag. This is set to true if project.aidl is modified. */
- private boolean mFullAidlCompilation = false;
-
/** Manifest check/parsing flag. */
private boolean mCheckedManifestXml = false;
@@ -75,36 +83,36 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
private boolean mInRes = false;
/**
- * In Source folder flag. This allows us to know if we're in a source
- * folder.
+ * Current Source folder. This allows us to know if we're in a source
+ * folder, and which folder.
*/
- private boolean mInSrc = false;
+ private IFolder mSourceFolder = null;
/** List of source folders. */
private ArrayList<IPath> mSourceFolders;
+ private boolean mIsGenSourceFolder = false;
+
+ private IWorkspaceRoot mRoot;
public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
super(builder);
mSourceFolders = sourceFolders;
+ mRoot = ResourcesPlugin.getWorkspace().getRoot();
}
public boolean getCompileResources() {
return mCompileResources;
}
- public ArrayList<IFile> getAidlToCompile() {
+ public ArrayList<AidlData> getAidlToCompile() {
return mAidlToCompile;
}
- public ArrayList<IFile> getAidlToRemove() {
+ public ArrayList<AidlData> getAidlToRemove() {
return mAidlToRemove;
}
- public boolean getFullAidlRecompilation() {
- return mFullAidlCompilation;
- }
-
/**
* Returns whether the manifest file was parsed/checked for error during the resource delta
* visiting.
@@ -149,11 +157,13 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// since the delta visitor also visits the root we return true if
// segments.length = 1
if (segments.length == 1) {
+ // FIXME: check this is an Android project.
return true;
} else if (segments.length == 2) {
// if we are at an item directly under the root directory,
// then we are not yet in a source or resource folder
- mInRes = mInSrc = false;
+ mInRes = false;
+ mSourceFolder = null;
if (SdkConstants.FD_RESOURCES.equalsIgnoreCase(segments[1])) {
// this is the resource folder that was modified. we want to
@@ -162,7 +172,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// since we're going to visit its children next, we set the
// flag
mInRes = true;
- mInSrc = false;
+ mSourceFolder = null;
return true;
} else if (AndroidConstants.FN_ANDROID_MANIFEST.equalsIgnoreCase(segments[1])) {
// any change in the manifest could trigger a new R.java
@@ -183,9 +193,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// we don't want to go to the children, not like they are
// any for this resource anyway.
return false;
- } else if (AndroidConstants.FN_PROJECT_AIDL.equalsIgnoreCase(segments[1])) {
- // need to force recompilation of all the aidl files
- mFullAidlCompilation = true;
}
}
@@ -198,7 +205,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// so first we test if we already know we are in a source or
// resource folder.
- if (mInSrc) {
+ if (mSourceFolder != null) {
// if we are in the res folder, we are looking for the following changes:
// - added/removed/modified aidl files.
// - missing R.java file
@@ -216,130 +223,84 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// get the modification kind
int kind = delta.getKind();
- if (kind == IResourceDelta.ADDED) {
- // we only care about added files (inside the source folders), if they
- // are aidl files.
+ // we process normal source folder and the 'gen' source folder differently.
+ if (mIsGenSourceFolder) {
+ // this is the generated java file source folder.
+ // - if R.java/Manifest.java are removed/modified, we recompile the resources
+ // - if aidl files are removed/modified, we recompile them.
- // get the extension of the resource
- String ext = resource.getFileExtension();
+ boolean outputWarning = false;
- if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
- // look for an already existing matching java file
- String javaName = resource.getName().replaceAll(
- AndroidConstants.RE_AIDL_EXT,
- AndroidConstants.DOT_JAVA);
-
- // get the parent container
- IContainer ic = resource.getParent();
-
- IFile javaFile = ic.getFile(new Path(javaName));
- if (javaFile != null && javaFile.exists()) {
- // check if that file was generated by the plugin. Normally those files are
- // deleted automatically, but it's better to check.
- String aidlPath = ProjectHelper.loadStringProperty(javaFile,
- PreCompilerBuilder.PROPERTY_ANDROID_GENERATED);
- if (aidlPath == null) {
- // mark the aidl file that it cannot be compile just yet
- ProjectHelper.saveBooleanProperty(file,
- PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, true);
- }
+ String fileName = resource.getName();
- // we add it anyway so that we can try to compile it at every compilation
- // until the conflict is fixed.
- mAidlToCompile.add(file);
+ // Special case of R.java/Manifest.java.
+ if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
+ AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
+ // if it was removed, there's a possibility that it was removed due to a
+ // package change, or an aidl that was removed, but the only thing
+ // that will happen is that we'll have an extra build. Not much of a problem.
+ mCompileResources = true;
- } else {
- // the java file doesn't exist, we can safely add the file to the list
- // of files to compile.
- mAidlToCompile.add(file);
+ // we want a warning
+ outputWarning = true;
+ } else {
+ // this has to be a Java file created from an aidl file.
+ // Look for the source aidl file in all the source folders.
+ String aidlFileName = fileName.replaceAll(AndroidConstants.RE_JAVA_EXT,
+ AndroidConstants.DOT_AIDL);
+
+ for (IPath sourceFolderPath : mSourceFolders) {
+ // do not search in the current source folder as it is the 'gen' folder.
+ if (sourceFolderPath.equals(mSourceFolder.getFullPath())) {
+ continue;
+ }
+
+ IFolder sourceFolder = getFolder(sourceFolderPath);
+ if (sourceFolder != null) {
+ // go recursively, segment by segment.
+ // index starts at 2 (0 is project, 1 is 'gen'
+ IFile sourceFile = findFile(sourceFolder, segments, 2, aidlFileName);
+
+ if (sourceFile != null) {
+ // found the source. add it to the list of files to compile
+ mAidlToCompile.add(new AidlData(sourceFolder, sourceFile));
+ outputWarning = true;
+ break;
+ }
+ }
}
}
- return false;
- }
-
- // get the filename
- String fileName = segments[segments.length - 1];
-
- boolean outputMessage = false;
-
- // Special case of R.java/Manifest.java.
- // FIXME: This does not check the package. Any modification of R.java/Manifest.java in another project will trigger a new recompilation of the resources.
- if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
- AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
- // if it was removed, there's a possibility that it was removed due to a
- // package change, or an aidl that was removed, but the only thing
- // that will happen is that we'll have an extra build. Not much of a problem.
- mCompileResources = true;
+ if (outputWarning) {
+ if (kind == IResourceDelta.REMOVED) {
+ // We pring an error just so that it's red, but it's just a warning really.
+ String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
+ AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
+ } else if (kind == IResourceDelta.CHANGED) {
+ // the file was modified manually! we can't allow it.
+ String msg = String.format(Messages.s_Modified_Manually_Recreating_s,
+ fileName);
+ AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
+ }
+ }
- // we want a warning
- outputMessage = true;
} else {
+ // this is another source folder.
+ // We only care about aidl files being added/modified/removed.
// get the extension of the resource
String ext = resource.getFileExtension();
-
if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
if (kind == IResourceDelta.REMOVED) {
- mAidlToRemove.add(file);
+ // we'll have to remove the generated file.
+ mAidlToRemove.add(new AidlData(mSourceFolder, file));
} else {
- mAidlToCompile.add(file);
- }
- } else {
- if (kind == IResourceDelta.REMOVED) {
- // the file has been removed. we need to check it's a java file and that
- // there's a matching aidl file. We can't check its persistent storage
- // anymore.
- if (AndroidConstants.EXT_JAVA.equalsIgnoreCase(ext)) {
- String aidlFile = resource.getName().replaceAll(
- AndroidConstants.RE_JAVA_EXT,
- AndroidConstants.DOT_AIDL);
-
- // get the parent container
- IContainer ic = resource.getParent();
-
- IFile f = ic.getFile(new Path(aidlFile));
- if (f != null && f.exists() ) {
- // make sure that the aidl file is not in conflict anymore, in
- // case the java file was not generated by us.
- if (ProjectHelper.loadBooleanProperty(f,
- PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, false)) {
- ProjectHelper.saveBooleanProperty(f,
- PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, false);
- } else {
- outputMessage = true;
- }
- mAidlToCompile.add(f);
- }
- }
- } else {
- // check if it's an android generated java file.
- IResource aidlSource = ProjectHelper.loadResourceProperty(
- file, PreCompilerBuilder.PROPERTY_ANDROID_GENERATED);
-
- if (aidlSource != null && aidlSource.exists() &&
- aidlSource.getType() == IResource.FILE) {
- // it looks like this was a java file created from an aidl file.
- // we need to add the aidl file to the list of aidl file to compile
- mAidlToCompile.add((IFile)aidlSource);
- outputMessage = true;
- }
+ // add the aidl file to the list of file to (re)compile
+ mAidlToCompile.add(new AidlData(mSourceFolder, file));
}
}
}
- if (outputMessage) {
- if (kind == IResourceDelta.REMOVED) {
- // We pring an error just so that it's red, but it's just a warning really.
- String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
- AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
- } else if (kind == IResourceDelta.CHANGED) {
- // the file was modified manually! we can't allow it.
- String msg = String.format(Messages.s_Modified_Manually_Recreating_s, fileName);
- AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
- }
- }
-
// no children.
return false;
} else if (mInRes) {
@@ -403,19 +364,25 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
}
} else if (resource instanceof IFolder) {
// in this case we may be inside a folder that contains a source
- // folder.
- String[] sourceFolderSegments = findMatchingSourceFolder(mSourceFolders, segments);
- if (sourceFolderSegments != null) {
- // we have a match!
- mInRes = false;
-
- // Check if the current folder is actually a source folder
- if (sourceFolderSegments.length == segments.length) {
- mInSrc = true;
+ // folder, go through the list of known source folders
+
+ for (IPath sourceFolderPath : mSourceFolders) {
+ // first check if they match exactly.
+ if (sourceFolderPath.equals(path)) {
+ // this is a source folder!
+ mInRes = false;
+ mSourceFolder = getFolder(sourceFolderPath); // all non null due to test above
+ mIsGenSourceFolder = path.segmentCount() == 2 &&
+ path.segment(1).equals(SdkConstants.FD_GEN_SOURCES);
+ return true;
}
- // and return true to visit the content, no matter what
- return true;
+ // check if we are on the way to a source folder.
+ int count = sourceFolderPath.matchingFirstSegments(path);
+ if (count == path.segmentCount()) {
+ mInRes = false;
+ return true;
+ }
}
// if we're here, we are visiting another folder
@@ -429,4 +396,46 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
return false;
}
+
+ /**
+ * Searches for and return a file in a folder. The file is defined by its segments, and a new
+ * name (replacing the last segment).
+ * @param folder the folder we are searching
+ * @param segments the segments of the file to search.
+ * @param index the index of the current segment we are looking for
+ * @param filename the new name to replace the last segment.
+ * @return the {@link IFile} representing the searched file, or null if not found
+ */
+ private IFile findFile(IFolder folder, String[] segments, int index, String filename) {
+ boolean lastSegment = index == segments.length - 1;
+ IResource resource = folder.findMember(lastSegment ? filename : segments[index]);
+ if (resource != null && resource.exists()) {
+ if (lastSegment) {
+ if (resource.getType() == IResource.FILE) {
+ return (IFile)resource;
+ }
+ } else {
+ if (resource.getType() == IResource.FOLDER) {
+ return findFile((IFolder)resource, segments, index+1, filename);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a handle to the folder identified by the given path in this container.
+ * <p/>The different with {@link IContainer#getFolder(IPath)} is that this returns a non
+ * null object only if the resource actually exists and is a folder (and not a file)
+ * @param path the path of the folder to return.
+ * @return a handle to the folder if it exists, or null otherwise.
+ */
+ private IFolder getFolder(IPath path) {
+ IResource resource = mRoot.findMember(path);
+ if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
+ return (IFolder)resource;
+ }
+
+ return null;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
index 19d7185..0255f9f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
@@ -19,19 +19,27 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.sdk.LoadStatus;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import java.util.ArrayList;
import java.util.Map;
/**
@@ -56,6 +64,10 @@ public class ResourceManagerBuilder extends BaseBuilder {
// Clear the project of the generic markers
BaseBuilder.removeMarkersFromProject(project, AdtConstants.MARKER_ADT);
+
+ // check for existing target marker, in which case we abort.
+ // (this means: no SDK, no target, or unresolvable target.)
+ abortOnBadSetup(project);
// Check the compiler compliance level, displaying the error message
// since this is the first builder.
@@ -83,8 +95,7 @@ public class ResourceManagerBuilder extends BaseBuilder {
String osSdkFolder = AdtPlugin.getOsSdkFolder();
if (osSdkFolder == null || osSdkFolder.length() == 0) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
- Messages.No_SDK_Setup_Error);
+ AdtPlugin.printErrorToConsole(project, Messages.No_SDK_Setup_Error);
markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
IMarker.SEVERITY_ERROR);
@@ -92,13 +103,6 @@ public class ResourceManagerBuilder extends BaseBuilder {
stopBuild(Messages.No_SDK_Setup_Error);
}
- // check if we have finished loading the SDK.
- if (AdtPlugin.getDefault().getSdkLoadStatus() != LoadStatus.LOADED) {
- // we exit silently
- // This interrupts the build. The next builders will not run.
- stopBuild("SDK is not loaded yet");
- }
-
// check the project has a target
IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
if (projectTarget == null) {
@@ -106,6 +110,85 @@ public class ResourceManagerBuilder extends BaseBuilder {
// This interrupts the build. The next builders will not run.
stopBuild("Project has no target");
}
+
+ // check the 'gen' source folder is present
+ boolean hasGenSrcFolder = false; // whether the project has a 'gen' source folder setup
+ IJavaProject javaProject = JavaCore.create(project);
+
+ IClasspathEntry[] classpaths = javaProject.readRawClasspath();
+ if (classpaths != null) {
+ for (IClasspathEntry e : classpaths) {
+ if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath path = e.getPath();
+ if (path.segmentCount() == 2 &&
+ path.segment(1).equals(SdkConstants.FD_GEN_SOURCES)) {
+ hasGenSrcFolder = true;
+ break;
+ }
+ }
+ }
+ }
+
+ boolean genFolderPresent = false; // whether the gen folder actually exists
+ IResource resource = project.findMember(SdkConstants.FD_GEN_SOURCES);
+ genFolderPresent = resource != null && resource.exists();
+
+ if (hasGenSrcFolder == false && genFolderPresent) {
+ // No source folder setup for 'gen' in the project, but there's already a
+ // 'gen' resource (file or folder).
+ String message;
+ if (resource.getType() == IResource.FOLDER) {
+ // folder exists already! This is an error. If the folder had been created
+ // by the NewProjectWizard, it'd be a source folder.
+ message = String.format("%1$s already exists but is not a source folder. Convert to a source folder or rename it.",
+ resource.getFullPath().toString());
+ } else {
+ // resource exists but is not a folder.
+ message = String.format(
+ "Resource %1$s is in the way. ADT needs a source folder called 'gen' to work. Rename or delete resource.",
+ resource.getFullPath().toString());
+ }
+
+ AdtPlugin.printErrorToConsole(project, message);
+ markProject(AdtConstants.MARKER_ADT, message, IMarker.SEVERITY_ERROR);
+
+ // This interrupts the build. The next builders will not run.
+ stopBuild(message);
+ } else if (hasGenSrcFolder == false || genFolderPresent == false) {
+ // either there is no 'gen' source folder in the project (older SDK),
+ // or the folder does not exist (was deleted, or was a fresh svn checkout maybe.)
+
+ // In case we are migrating from an older SDK, we go through the current source
+ // folders and delete the generated Java files.
+ ArrayList<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ for (IPath path : sourceFolders) {
+ IResource member = root.findMember(path);
+ if (member != null) {
+ removeDerivedResources(member, monitor);
+ }
+ }
+
+ // create the new source folder, if needed
+ IFolder genFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
+ if (genFolderPresent == false) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+ "Creating 'gen' source folder for generated Java files");
+ genFolder.create(true /* force */, true /* local */,
+ new SubProgressMonitor(monitor, 10));
+ }
+
+ // add it to the source folder list, if needed only (or it will throw)
+ if (hasGenSrcFolder == false) {
+ IClasspathEntry[] entries = javaProject.getRawClasspath();
+ entries = ProjectHelper.addEntryToClasspath(entries,
+ JavaCore.newSourceEntry(genFolder.getFullPath()));
+ javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 10));
+ }
+
+ // refresh the whole project
+ project.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 10));
+ }
// Check the preference to be sure we are supposed to refresh
// the folders.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
index 3d60401..7029206 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunchConfiguration;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
index ac003df..9c5f09b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Client;
@@ -28,8 +28,7 @@ import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.ddmlib.SyncService.SyncResult;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
-import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
+import com.android.ide.eclipse.adt.launch.DeviceChooserDialog.DeviceChooserResponse;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
index a260350..275addf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Client;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java
index d919c1f..5b4cdbb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java
new file mode 100644
index 0000000..7a74309
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.SdkConstants;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate;
+import org.osgi.framework.Bundle;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * <p>
+ * For Android projects, android.jar gets added to the launch configuration of
+ * JUnit tests as a bootstrap entry. This breaks JUnit tests as android.jar
+ * contains a skeleton version of JUnit classes and the JVM will stop with an error similar
+ * to: <blockquote> Error occurred during initialization of VM
+ * java/lang/NoClassDefFoundError: java/lang/ref/FinalReference </blockquote>
+ * <p>
+ * At compile time, Eclipse does not know that there is no valid junit.jar in
+ * the classpath since it can find a correct reference to all the necessary
+ * org.junit.* classes in the android.jar so it does not prompt the user to add
+ * the JUnit3 or JUnit4 jar.
+ * <p>
+ * This delegates removes the android.jar from the bootstrap path and if
+ * necessary also puts back the junit.jar in the user classpath.
+ * <p>
+ * This delegate will be present for both Java and Android projects (delegates
+ * setting instead of only the current project) but the behavior for Java
+ * projects should be neutral since:
+ * <ol>
+ * <li>Java tests can only compile (and then run) when a valid junit.jar is
+ * present
+ * <li>There is no android.jar in Java projects
+ * </ol>
+ */
+public class JUnitLaunchConfigDelegate extends JUnitLaunchConfigurationDelegate {
+
+ private static final String JUNIT_JAR = "junit.jar"; //$NON-NLS-1$
+
+ @Override
+ public String[][] getBootpathExt(ILaunchConfiguration configuration) throws CoreException {
+ String[][] bootpath = super.getBootpathExt(configuration);
+ return fixBootpathExt(bootpath);
+ }
+
+ @Override
+ public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
+ String[] classpath = super.getClasspath(configuration);
+ return fixClasspath(classpath, getJavaProjectName(configuration));
+ }
+
+ /**
+ * Removes the android.jar from the bootstrap path if present.
+ *
+ * @param bootpath Array of Arrays of bootstrap class paths
+ * @return a new modified (if applicable) bootpath
+ */
+ public static String[][] fixBootpathExt(String[][] bootpath) {
+ for (int i = 0; i < bootpath.length; i++) {
+ if (bootpath[i] != null) {
+ // we assume that the android.jar can only be present in the
+ // bootstrap path of android tests
+ if (bootpath[i][0].endsWith(SdkConstants.FN_FRAMEWORK_LIBRARY)) {
+ bootpath[i] = null;
+ }
+ }
+ }
+ return bootpath;
+ }
+
+ /**
+ * Add the junit.jar to the user classpath; since Eclipse was relying on
+ * android.jar to provide the appropriate org.junit classes, it does not
+ * know it actually needs the junit.jar.
+ *
+ * @param classpath Array containing classpath
+ * @param projectName The name of the project (for logging purposes)
+ *
+ * @return a new modified (if applicable) classpath
+ */
+ public static String[] fixClasspath(String[] classpath, String projectName) {
+ // search for junit.jar; if any are found return immediately
+ for (int i = 0; i < classpath.length; i++) {
+ if (classpath[i].endsWith(JUNIT_JAR)) {
+ return classpath;
+ }
+ }
+
+ // This delegate being called without a junit.jar present is only
+ // possible for Android projects. In a non-Android project, the test
+ // would not compile and would be unable to run.
+ try {
+ // junit4 is backward compatible with junit3 and they uses the
+ // same junit.jar from bundle org.junit:
+ // When a project has mixed JUnit3 and JUnit4 tests, if JUnit3 jar
+ // is added first it is then replaced by the JUnit4 jar when user is
+ // prompted to fix the JUnit4 test failure
+ String jarLocation = getJunitJarLocation();
+ // we extend the classpath by one element and append junit.jar
+ String[] newClasspath = new String[classpath.length + 1];
+ System.arraycopy(classpath, 0, newClasspath, 0, classpath.length);
+ newClasspath[newClasspath.length - 1] = jarLocation;
+ classpath = newClasspath;
+ } catch (IOException e) {
+ // This should not happen as we depend on the org.junit
+ // plugin explicitly; the error is logged here so that the user can
+ // trace back the cause when the test fails to run
+ AdtPlugin.log(e, "Could not find a valid junit.jar");
+ AdtPlugin.printErrorToConsole(projectName,
+ "Could not find a valid junit.jar");
+ // Return the classpath as-is (with no junit.jar) anyway because we
+ // will let the actual launch config fails.
+ }
+
+ return classpath;
+ }
+
+ /**
+ * Returns the path of the junit jar in the highest version bundle.
+ *
+ * (This is public only so that the test can call it)
+ *
+ * @return the path as a string
+ * @throws IOException
+ */
+ public static String getJunitJarLocation() throws IOException {
+ Bundle bundle = Platform.getBundle("org.junit"); //$NON-NLS-1$
+ if (bundle == null) {
+ throw new IOException("Cannot find org.junit bundle");
+ }
+ URL jarUrl = bundle.getEntry(AndroidConstants.WS_SEP + JUNIT_JAR);
+ return FileLocator.resolve(jarUrl).getFile();
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
index bbd320b..a46f56c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController.AndroidLaunchConfiguration;
+import com.android.ide.eclipse.adt.launch.AndroidLaunchController.AndroidLaunchConfiguration;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java
index c0dbd54..f1dbd26 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
import org.eclipse.debug.ui.CommonTab;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java
index 92677f1..6b2744c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java
index 6a40ed0..599da5f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
deleted file mode 100644
index a1b3c38..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.project;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Action going through all the source of a project and creating a pre-processed aidl file
- * with all the custom parcelable classes.
- */
-public class CreateAidlImportAction implements IObjectActionDelegate {
-
- private ISelection mSelection;
-
- public CreateAidlImportAction() {
- // pass
- }
-
- public void setActivePart(IAction action, IWorkbenchPart targetPart) {
- // pass
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
- */
- public void run(IAction action) {
- if (mSelection instanceof IStructuredSelection) {
- for (Iterator<?> it = ((IStructuredSelection)mSelection).iterator(); it.hasNext();) {
- Object element = it.next();
- IProject project = null;
- if (element instanceof IProject) {
- project = (IProject)element;
- } else if (element instanceof IAdaptable) {
- project = (IProject)((IAdaptable)element).getAdapter(IProject.class);
- }
- if (project != null) {
- final IProject fproject = project;
- new Job("Aidl preprocess") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- return createImportFile(fproject, monitor);
- }
- }.schedule();
- }
- }
- }
- }
-
- public void selectionChanged(IAction action, ISelection selection) {
- mSelection = selection;
- }
-
- private IStatus createImportFile(IProject project, IProgressMonitor monitor) {
- try {
- if (monitor != null) {
- monitor.beginTask(String.format(
- "Creating aid preprocess file for %1$s", project.getName()), 1);
- }
-
- ArrayList<String> parcelables = new ArrayList<String>();
-
- IJavaProject javaProject = JavaCore.create(project);
-
- IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
-
- for (IPackageFragmentRoot root : roots) {
- if (root.isArchive() == false && root.isExternal() == false) {
- parsePackageFragmentRoot(root, parcelables, monitor);
- }
- }
-
- // create the file with the parcelables
- if (parcelables.size() > 0) {
- IPath path = project.getLocation();
- path = path.append(AndroidConstants.FN_PROJECT_AIDL);
-
- File f = new File(path.toOSString());
- if (f.exists() == false) {
- if (f.createNewFile() == false) {
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
- "Failed to create /project.aidl");
- }
- }
-
- FileWriter fw = new FileWriter(f);
-
- fw.write("// This file is auto-generated by the\n");
- fw.write("// 'Create Aidl preprocess file for Parcelable classes'\n");
- fw.write("// action. Do not modify!\n\n");
-
- for (String parcelable : parcelables) {
- fw.write("parcelable "); //$NON-NLS-1$
- fw.write(parcelable);
- fw.append(";\n"); //$NON-NLS-1$
- }
-
- fw.close();
-
- // need to refresh the level just below the project to make sure it's being picked
- // up by eclipse.
- project.refreshLocal(IResource.DEPTH_ONE, monitor);
- }
-
- if (monitor != null) {
- monitor.worked(1);
- monitor.done();
- }
-
- return Status.OK_STATUS;
- } catch (JavaModelException e) {
- return e.getJavaModelStatus();
- } catch (IOException e) {
- return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
- "Failed to create /project.aidl", e);
- } catch (CoreException e) {
- return e.getStatus();
- } finally {
- if (monitor != null) {
- monitor.done();
- }
- }
- }
-
- private void parsePackageFragmentRoot(IPackageFragmentRoot root,
- ArrayList<String> parcelables, IProgressMonitor monitor) throws JavaModelException {
-
- IJavaElement[] elements = root.getChildren();
-
- for (IJavaElement element : elements) {
- if (element instanceof IPackageFragment) {
- ICompilationUnit[] compilationUnits =
- ((IPackageFragment)element).getCompilationUnits();
-
- for (ICompilationUnit unit : compilationUnits) {
- IType[] types = unit.getTypes();
-
- for (IType type : types) {
- parseType(type, parcelables, monitor);
- }
- }
- }
- }
- }
-
- private void parseType(IType type, ArrayList<String> parcelables, IProgressMonitor monitor)
- throws JavaModelException {
- // first look in this type if it somehow extends parcelable.
- ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(monitor);
-
- IType[] superInterfaces = typeHierarchy.getAllSuperInterfaces(type);
- for (IType superInterface : superInterfaces) {
- if (AndroidConstants.CLASS_PARCELABLE.equals(superInterface.getFullyQualifiedName())) {
- parcelables.add(type.getFullyQualifiedName());
- }
- }
-
- // then look in inner types.
- IType[] innerTypes = type.getTypes();
-
- for (IType innerType : innerTypes) {
- parseType(innerType, parcelables, monitor);
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
index b8a0b0c..49bbd81 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
@@ -17,7 +17,7 @@
package com.android.ide.eclipse.adt.project;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
+import com.android.ide.eclipse.adt.launch.LaunchConfigDelegate;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
index 7fc3318..59b2b06 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
@@ -39,7 +39,7 @@ public class FolderDecorator implements ILightweightLabelDecorator {
private ImageDescriptor mDescriptor;
public FolderDecorator() {
- mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png");
+ mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png"); //$NON-NLS-1$
}
public void decorate(Object element, IDecoration decoration) {
@@ -55,13 +55,13 @@ public class FolderDecorator implements ILightweightLabelDecorator {
if (folder.getParent().getType() == IResource.PROJECT) {
String name = folder.getName();
if (name.equals(SdkConstants.FD_ASSETS)) {
- decorate(decoration, " [Android assets]");
- decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ doDecoration(decoration, null);
} else if (name.equals(SdkConstants.FD_RESOURCES)) {
- decorate(decoration, " [Android resources]");
- decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
- } else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
- decorate(decoration, " [Native Libraries]");
+ doDecoration(decoration, null);
+ } else if (name.equals(SdkConstants.FD_GEN_SOURCES)) {
+ doDecoration(decoration, " [Generated Java Files]");
+ } else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
+ doDecoration(decoration, null);
}
}
}
@@ -72,20 +72,24 @@ public class FolderDecorator implements ILightweightLabelDecorator {
}
}
- public void decorate(IDecoration decoration, String suffix) {
- decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ public void doDecoration(IDecoration decoration, String suffix) {
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_LEFT);
- // this is broken as it changes the color of the whole text, not only of the decoration.
- // TODO: figure out how to change the color of the decoration only.
-// decoration.addSuffix(suffix);
-// ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
-// ColorRegistry registry = theme.getColorRegistry();
-// decoration.setForegroundColor(registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations"));
+ if (suffix != null) {
+ decoration.addSuffix(suffix);
+
+ // this is broken as it changes the color of the whole text, not only of the decoration.
+ // TODO: figure out how to change the color of the decoration only.
+// ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
+// ColorRegistry registry = theme.getColorRegistry();
+// decoration.setForegroundColor(
+// registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations")); //$NON-NLS-1$
+ }
}
public boolean isLabelProperty(Object element, String property) {
- // at this time return false.
+ // Property change do not affect the label
return false;
}
@@ -93,13 +97,11 @@ public class FolderDecorator implements ILightweightLabelDecorator {
// No state change will affect the rendering.
}
-
-
public void removeListener(ILabelProviderListener listener) {
// No state change will affect the rendering.
}
public void dispose() {
- // nothind to dispose
+ // nothing to dispose
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
index e201132..5abfd81 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
@@ -87,7 +87,6 @@ public class AndroidConstants {
/** Name of the manifest file, i.e. "AndroidManifest.xml". */
public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$
- public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$
/** Name of the android sources directory */
public static final String FD_ANDROID_SOURCES = "sources"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index 266008c..c7f5ba8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -13,7 +13,7 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.jdt.launching,
org.eclipse.ui.views,
com.android.ide.eclipse.ddms
-Eclipse-LazyStart: true
+Bundle-ActivationPolicy: lazy
Bundle-Vendor: The Android Open Source Project
Bundle-ClassPath: kxml2-2.3.0.jar,
.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java
new file mode 100644
index 0000000..df3745e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import java.io.IOException;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+public class JUnitLaunchConfigDelegateTest extends TestCase {
+
+ public void testAbleToFetchJunitJar() throws IOException {
+ assertTrue(JUnitLaunchConfigDelegate.getJunitJarLocation().endsWith("junit.jar"));
+ }
+
+ public void testFixBootpathExtWithAndroidJar() {
+ String[][] testArray = {
+ null,
+ { "android.jar"},
+ null,
+ { "some_other_jar.jar" },
+ };
+
+ String[][] expectedArray = {
+ null,
+ null,
+ null,
+ { "some_other_jar.jar" },
+ };
+
+ assertEqualsArrays(expectedArray, JUnitLaunchConfigDelegate.fixBootpathExt(testArray));
+ }
+
+ public void testFixBootpathExtWithNoAndroidJar() {
+ String[][] testArray = {
+ null,
+ { "somejar.jar"},
+ null,
+ };
+
+ String[][] expectedArray = {
+ null,
+ { "somejar.jar"},
+ null,
+ };
+
+ assertEqualsArrays(expectedArray, JUnitLaunchConfigDelegate.fixBootpathExt(testArray));
+ }
+
+ public void testFixClasspathWithJunitJar() throws IOException {
+ String[] testArray = {
+ JUnitLaunchConfigDelegate.getJunitJarLocation(),
+ };
+
+ String[] expectedArray = {
+ JUnitLaunchConfigDelegate.getJunitJarLocation(),
+ };
+
+ assertEqualsArrays(expectedArray,
+ JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+ }
+
+ public void testFixClasspathWithoutJunitJar() throws IOException {
+ String[] testArray = {
+ "random.jar",
+ };
+
+ String[] expectedArray = {
+ "random.jar",
+ JUnitLaunchConfigDelegate.getJunitJarLocation(),
+ };
+
+ assertEqualsArrays(expectedArray,
+ JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+ }
+
+
+ public void testFixClasspathWithNoJars() throws IOException {
+ String[] testArray = {
+ };
+
+ String[] expectedArray = {
+ JUnitLaunchConfigDelegate.getJunitJarLocation(),
+ };
+
+ assertEqualsArrays(expectedArray,
+ JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+ }
+
+ private void assertEqualsArrays(String[][] a1, String[][] a2) {
+ assertTrue(Arrays.deepEquals(a1, a2));
+ }
+
+ private void assertEqualsArrays(String[] a1, String[] a2) {
+ assertTrue(Arrays.deepEquals(a1, a2));
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
index 29538bb..6aaa209 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
@@ -15,15 +15,14 @@
*/
package com.android.ide.eclipse.tests;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
import org.eclipse.core.runtime.Plugin;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;
-import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
/**
* Class for collecting all test cases in an eclipse plugin
@@ -31,8 +30,6 @@ import java.util.logging.Logger;
*/
public class EclipseTestCollector {
- private static final Logger sLogger = Logger.getLogger(EclipseTestCollector.class.getName());
-
/**
* Constructor
*/
@@ -49,13 +46,13 @@ public class EclipseTestCollector {
*/
public void addTestCases(TestSuite suite, Plugin plugin, String expectedPackage) {
if (plugin != null) {
- Enumeration entries = plugin.getBundle().findEntries("/", "*.class", true);
+ Enumeration<?> entries = plugin.getBundle().findEntries("/", "*.class", true);
while (entries.hasMoreElements()) {
URL entry = (URL)entries.nextElement();
String filePath = entry.getPath().replace(".class", "");
try {
- Class testClass = getClass(filePath, expectedPackage);
+ Class<?> testClass = getClass(filePath, expectedPackage);
if (isTestClass(testClass)) {
suite.addTestSuite(testClass);
}
@@ -69,11 +66,11 @@ public class EclipseTestCollector {
}
/**
- * Returns true if given class shouk\ld be added to suite
+ * Returns true if given class should be added to suite
* @param testClass
* @return
*/
- protected boolean isTestClass(Class testClass) {
+ protected boolean isTestClass(Class<?> testClass) {
return TestCase.class.isAssignableFrom(testClass) &&
Modifier.isPublic(testClass.getModifiers()) &&
hasPublicConstructor(testClass);
@@ -84,7 +81,7 @@ public class EclipseTestCollector {
* @param testClass
* @return
*/
- protected boolean hasPublicConstructor(Class testClass) {
+ protected boolean hasPublicConstructor(Class<?> testClass) {
try {
TestSuite.getTestConstructor(testClass);
} catch(NoSuchMethodException e) {
@@ -100,7 +97,7 @@ public class EclipseTestCollector {
* @return
* @throws ClassNotFoundException
*/
- protected Class getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
+ protected Class<?> getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
String dotPath = filePath.replace('/', '.');
// remove the output folders, by finding where package name starts
int index = dotPath.indexOf(expectedPackage);
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
index ac928db..67e7cb2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
@@ -49,7 +49,7 @@ public class UnitTests {
* Override parent class to exclude functional tests
*/
@Override
- protected boolean isTestClass(Class testClass) {
+ protected boolean isTestClass(Class<?> testClass) {
return super.isTestClass(testClass) &&
!testClass.getPackage().getName().startsWith(FuncTests.FUNC_TEST_PACKAGE);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
index 25a86c3..46e60ba 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
@@ -31,7 +31,6 @@ import com.android.ide.eclipse.mock.FolderMock;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.util.ArrayList;
import junit.framework.TestCase;
@@ -47,7 +46,6 @@ public class ConfigMatchTest extends TestCase {
private FolderConfiguration config2;
private FolderConfiguration config1;
- @SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
index 6a555a4..0920f00 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
@@ -20,7 +20,6 @@ import com.android.ide.eclipse.editors.resources.configurations.FolderConfigurat
import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier;
import java.lang.reflect.Field;
-import java.util.ArrayList;
import junit.framework.TestCase;
@@ -41,7 +40,6 @@ public class QualifierListTest extends TestCase {
mManager = null;
}
- @SuppressWarnings("unchecked")
public void testQualifierList() {
try {
// get the list of qualifier in the resource manager
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
index a95286c..2220ed1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
@@ -424,11 +424,13 @@ public class FileMock implements IFile {
throw new NotImplementedException();
}
- public Map getPersistentProperties() throws CoreException {
+ @SuppressWarnings("unchecked")
+ public Map getPersistentProperties() throws CoreException {
throw new NotImplementedException();
}
- public Map getSessionProperties() throws CoreException {
+ @SuppressWarnings("unchecked")
+ public Map getSessionProperties() throws CoreException {
throw new NotImplementedException();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
index 223deb0..73a69aa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
@@ -428,11 +428,11 @@ public final class FolderMock implements IFolder {
throw new NotImplementedException();
}
- public Map getPersistentProperties() throws CoreException {
+ public Map<?,?> getPersistentProperties() throws CoreException {
throw new NotImplementedException();
}
- public Map getSessionProperties() throws CoreException {
+ public Map<?,?> getSessionProperties() throws CoreException {
throw new NotImplementedException();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
index 4c409dc..0e6fde0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
@@ -42,6 +42,7 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.net.URI;
import java.util.Map;
+@SuppressWarnings("deprecation")
public class ProjectMock implements IProject {
public void build(int kind, IProgressMonitor monitor) throws CoreException {
@@ -95,7 +96,6 @@ public class ProjectMock implements IProject {
throw new NotImplementedException();
}
- @SuppressWarnings("deprecation")
public IPath getPluginWorkingLocation(IPluginDescriptor plugin) {
throw new NotImplementedException();
}
@@ -459,6 +459,8 @@ public class ProjectMock implements IProject {
throw new NotImplementedException();
}
+
+ @SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
throw new NotImplementedException();
}
@@ -476,11 +478,11 @@ public class ProjectMock implements IProject {
throw new NotImplementedException();
}
- public Map getPersistentProperties() throws CoreException {
+ public Map<?,?> getPersistentProperties() throws CoreException {
throw new NotImplementedException();
}
- public Map getSessionProperties() throws CoreException {
+ public Map<?,?> getSessionProperties() throws CoreException {
throw new NotImplementedException();
}
diff --git a/ninepatch/src/com/android/ninepatch/NinePatch.java b/ninepatch/src/com/android/ninepatch/NinePatch.java
index 39e05c6..35a1824 100644
--- a/ninepatch/src/com/android/ninepatch/NinePatch.java
+++ b/ninepatch/src/com/android/ninepatch/NinePatch.java
@@ -127,8 +127,7 @@ public class NinePatch {
try {
- if (mPatches.size() == 0 || mHorizontalPatches.size() == 0 ||
- mVerticalPatches.size() == 0) {
+ if (mPatches.size() == 0) {
g.drawImage(mImage, x, y, scaledWidth, scaledHeight, null);
return;
}
@@ -254,6 +253,14 @@ public class NinePatch {
start = rect.x;
}
}
+ } else {
+ int start = -1;
+ for (Rectangle rect : mPatches) {
+ if (rect.x > start) {
+ mHorizontalPatchesSum += rect.width;
+ start = rect.x;
+ }
+ }
}
mVerticalPatchesSum = 0;
@@ -265,6 +272,14 @@ public class NinePatch {
start = rect.y;
}
}
+ } else {
+ int start = -1;
+ for (Rectangle rect : mPatches) {
+ if (rect.y > start) {
+ mVerticalPatchesSum += rect.height;
+ start = rect.y;
+ }
+ }
}
}
@@ -286,28 +301,11 @@ public class NinePatch {
boolean[] result = new boolean[1];
Pair<List<Pair<Integer>>> left = getPatches(column, result);
mVerticalStartWithPatch = result[0];
-
- // compute the min size, based on the list of fixed sections, which is stored in
- // Pair.mFirst
- mMinHeight = 0;
- List<Pair<Integer>> fixedSections = left.mFirst;
- for (Pair<Integer> section : fixedSections) {
- mMinHeight += section.mSecond - section.mFirst;
- }
result = new boolean[1];
Pair<List<Pair<Integer>>> top = getPatches(row, result);
mHorizontalStartWithPatch = result[0];
- // compute the min size, based on the list of fixed sections, which is stored in
- // Pair.mFirst
-
- mMinWidth = 0;
- fixedSections = top.mFirst;
- for (Pair<Integer> section : fixedSections) {
- mMinWidth += section.mSecond - section.mFirst;
- }
-
mFixed = getRectangles(left.mFirst, top.mFirst);
mPatches = getRectangles(left.mSecond, top.mSecond);
@@ -315,7 +313,15 @@ public class NinePatch {
mHorizontalPatches = getRectangles(left.mFirst, top.mSecond);
mVerticalPatches = getRectangles(left.mSecond, top.mFirst);
} else {
- mHorizontalPatches = mVerticalPatches = new ArrayList<Rectangle>(0);
+ if (top.mFirst.size() > 0) {
+ mHorizontalPatches = new ArrayList<Rectangle>(0);
+ mVerticalPatches = getVerticalRectangles(top.mFirst);
+ } else if (left.mFirst.size() > 0) {
+ mHorizontalPatches = getHorizontalRectangles(left.mFirst);
+ mVerticalPatches = new ArrayList<Rectangle>(0);
+ } else {
+ mHorizontalPatches = mVerticalPatches = new ArrayList<Rectangle>(0);
+ }
}
row = GraphicsUtilities.getPixels(mImage, 0, height - 1, width, 1, row);
@@ -326,31 +332,30 @@ public class NinePatch {
left = getPatches(column, result);
mVerticalPadding = getPadding(left.mFirst);
-
- mHorizontalPatchesSum = 0;
- if (mHorizontalPatches.size() > 0) {
- int start = -1;
- for (Rectangle rect : mHorizontalPatches) {
- if (rect.x > start) {
- mHorizontalPatchesSum += rect.width;
- start = rect.x;
- }
- }
- }
+ }
- mVerticalPatchesSum = 0;
- if (mVerticalPatches.size() > 0) {
- int start = -1;
- for (Rectangle rect : mVerticalPatches) {
- if (rect.y > start) {
- mVerticalPatchesSum += rect.height;
- start = rect.y;
- }
- }
+ private List<Rectangle> getVerticalRectangles(List<Pair<Integer>> topPairs) {
+ List<Rectangle> rectangles = new ArrayList<Rectangle>();
+ for (Pair<Integer> top : topPairs) {
+ int x = top.mFirst;
+ int width = top.mSecond - top.mFirst;
+
+ rectangles.add(new Rectangle(x, 1, width, mImage.getHeight() - 2));
}
+ return rectangles;
+ }
+ private List<Rectangle> getHorizontalRectangles(List<Pair<Integer>> leftPairs) {
+ List<Rectangle> rectangles = new ArrayList<Rectangle>();
+ for (Pair<Integer> left : leftPairs) {
+ int y = left.mFirst;
+ int height = left.mSecond - left.mFirst;
+
+ rectangles.add(new Rectangle(1, y, mImage.getWidth() - 2, height));
+ }
+ return rectangles;
}
-
+
private Pair<Integer> getPadding(List<Pair<Integer>> pairs) {
if (pairs.size() == 0) {
return new Pair<Integer>(0, 0);
@@ -366,14 +371,14 @@ public class NinePatch {
pairs.get(index).mSecond - pairs.get(index).mFirst);
}
}
-
+
private List<Rectangle> getRectangles(List<Pair<Integer>> leftPairs,
List<Pair<Integer>> topPairs) {
List<Rectangle> rectangles = new ArrayList<Rectangle>();
for (Pair<Integer> left : leftPairs) {
int y = left.mFirst;
int height = left.mSecond - left.mFirst;
- for (Pair<Integer> top: topPairs) {
+ for (Pair<Integer> top : topPairs) {
int x = top.mFirst;
int width = top.mSecond - top.mFirst;
@@ -382,7 +387,7 @@ public class NinePatch {
}
return rectangles;
}
-
+
private Pair<List<Pair<Integer>>> getPatches(int[] pixels, boolean[] startWithPatch) {
int lastIndex = 1;
int lastPixel = pixels[1];
@@ -390,7 +395,7 @@ public class NinePatch {
List<Pair<Integer>> fixed = new ArrayList<Pair<Integer>>();
List<Pair<Integer>> patches = new ArrayList<Pair<Integer>>();
-
+
for (int i = 1; i < pixels.length - 1; i++) {
int pixel = pixels[i];
if (pixel != lastPixel) {
@@ -418,6 +423,7 @@ public class NinePatch {
startWithPatch[0] = true;
fixed.clear();
}
+
return new Pair<List<Pair<Integer>>>(fixed, patches);
}