diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-09 11:52:11 -0700 | 
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-09 11:52:11 -0700 | 
| commit | 67dc23a61d888ba1b39fe6ed23d9f4d1a3df80ee (patch) | |
| tree | a42bec75db95d97b137dae37faa2838867475437 /eclipse | |
| parent | 72a9d2164d9207c39fbcfa2db51b4aa4f927a9dd (diff) | |
| download | sdk-67dc23a61d888ba1b39fe6ed23d9f4d1a3df80ee.zip sdk-67dc23a61d888ba1b39fe6ed23d9f4d1a3df80ee.tar.gz sdk-67dc23a61d888ba1b39fe6ed23d9f4d1a3df80ee.tar.bz2 | |
auto import from //branches/cupcake/...@137197
Diffstat (limited to 'eclipse')
31 files changed, 1112 insertions, 1157 deletions
| 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();  	} | 
