diff options
author | Stefan Xenos | 2016-11-19 03:30:15 +0000 |
---|---|---|
committer | Stefan Xenos | 2016-12-21 19:12:18 +0000 |
commit | f7ed9839ef5f6bfc6dd1db3bdc1a458b7b45c64b (patch) | |
tree | 738529eaaa35d3557a4855aae0ad59df6e0b4a57 | |
parent | 6ad94a9ef57eda351ed99bde761c01b798ba1ec1 (diff) | |
download | eclipse.jdt.core-f7ed9839ef5f6bfc6dd1db3bdc1a458b7b45c64b.tar.gz eclipse.jdt.core-f7ed9839ef5f6bfc6dd1db3bdc1a458b7b45c64b.tar.xz eclipse.jdt.core-f7ed9839ef5f6bfc6dd1db3bdc1a458b7b45c64b.zip |
Bug 507795 - Functional dynamic dependenciesI20161221-2000
Write the JDT core handler for dynamic dependencies.
Change-Id: I661fa11ac9d5ad36c5b70ae0654a7dcec26aa4cf
Signed-off-by: Stefan Xenos <sxenos@gmail.com>
9 files changed, 56 insertions, 160 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java index 2cc72b8322..6cafb5bb0e 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java @@ -1030,7 +1030,7 @@ public void testContainerInitializer25() throws CoreException { assertResourcesEqual( "Unexpected project references on startup", "/P1", - p2.getProject().getDescription().getDynamicReferences()); + p2.getProject().getReferencedProjects()); } finally { deleteProject("P1"); deleteProject("P2"); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java index 970c74f187..e6535c2cec 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java @@ -5663,7 +5663,7 @@ public void testUpdateProjectReferences() throws CoreException { createJavaProject("P1"); IJavaProject p = createJavaProject("P2"); p.setRawClasspath(new IClasspathEntry[] {JavaCore.newProjectEntry(new Path("/P1"))}, null); - IProject[] references = p.getProject().getDescription().getDynamicReferences(); + IProject[] references = p.getProject().getReferencedProjects(); assertResourcesEqual( "Unexpected resources", "/P1", diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java index 9ea4398ee4..a15213f4ec 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java @@ -1797,7 +1797,7 @@ public void testProjectOpen() throws CoreException { p2.open(null); waitForManualRefresh(); waitForAutoBuild(); - IProject[] references = p2.getDescription().getDynamicReferences(); + IProject[] references = p2.getReferencedProjects(); assertResourcesEqual( "Unexpected referenced projects", "/P1", diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java index 9e8b329a03..45740257b4 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java @@ -54,10 +54,7 @@ public abstract class ChangeClasspathOperation extends JavaModelOperation { // delta, indexing and classpath markers are going to be created by the delta processor // while handling the resource change (either .classpath change, or project touched) - // however ensure project references are updated - // since some clients rely on the project references when run inside an IWorkspaceRunnable - new ProjectReferenceChange(project, change.oldResolvedClasspath).updateProjectReferencesIfNecessary(); - + project.getProject().clearCachedDynamicReferences(); // and ensure that external folders are updated as well new ExternalFolderChange(project, change.oldResolvedClasspath).updateExternalFoldersIfNecessary(refreshExternalFolder, null); @@ -80,7 +77,8 @@ public abstract class ChangeClasspathOperation extends JavaModelOperation { } if ((result & ClasspathChange.HAS_PROJECT_CHANGE) != 0) { // ensure project references are updated on next build - state.addProjectReferenceChange(project, change.oldResolvedClasspath); + project.getProject().clearCachedDynamicReferences(); + state.addProjectReferenceChange(project); } if ((result & ClasspathChange.HAS_LIBRARY_CHANGE) != 0) { // ensure external folders are updated on next build diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java index bfcd867b31..22a6828598 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java @@ -102,7 +102,7 @@ public class DeltaProcessingState implements IResourceChangeListener, Indexer.Li private HashMap classpathValidations = new HashMap(); /* A table from JavaProject to ProjectReferenceChange */ - private HashMap projectReferenceChanges = new HashMap(); + private HashSet<IJavaProject> projectReferenceChanges = new HashSet<>(); /* A table from JavaProject to ExternalFolderChange */ private HashMap externalFolderChanges = new HashMap(); @@ -228,15 +228,11 @@ public class DeltaProcessingState implements IResourceChangeListener, Indexer.Li if (change == null) { change = new ExternalFolderChange(project, oldResolvedClasspath); this.externalFolderChanges.put(project, change); - } + } } - public synchronized void addProjectReferenceChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) { - ProjectReferenceChange change = (ProjectReferenceChange) this.projectReferenceChanges.get(project); - if (change == null) { - change = new ProjectReferenceChange(project, oldResolvedClasspath); - this.projectReferenceChanges.put(project, change); - } + public synchronized void addProjectReferenceChange(IJavaProject project) { + this.projectReferenceChanges.add(project); } public void initializeRoots(boolean initAfterLoad) { @@ -387,13 +383,10 @@ public class DeltaProcessingState implements IResourceChangeListener, Indexer.Li return updates; } - public synchronized ProjectReferenceChange[] removeProjectReferenceChanges() { - int length = this.projectReferenceChanges.size(); - if (length == 0) return null; - ProjectReferenceChange[] updates = new ProjectReferenceChange[length]; - this.projectReferenceChanges.values().toArray(updates); - this.projectReferenceChanges.clear(); - return updates; + public synchronized Set<IJavaProject> removeProjectReferenceChanges() { + Set<IJavaProject> result = this.projectReferenceChanges; + this.projectReferenceChanges = new HashSet<>(); + return result; } public synchronized HashSet removeExternalElementsToRefresh() { @@ -656,5 +649,4 @@ public class DeltaProcessingState implements IResourceChangeListener, Indexer.Li this.deltaProcessors.set(null); } } - } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java index 5311235038..59fe26bb94 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java @@ -591,8 +591,8 @@ public class DeltaProcessor { } private void checkProjectReferenceChange(IProject project, JavaProject javaProject) { - ClasspathChange change = this.state.getClasspathChange(project); - this.state.addProjectReferenceChange(javaProject, change == null ? null : change.oldResolvedClasspath); + project.clearCachedDynamicReferences(); + this.state.addProjectReferenceChange(javaProject); } private void readRawClasspath(JavaProject javaProject) { @@ -2080,7 +2080,8 @@ public class DeltaProcessor { this.state.addClasspathValidation(change.project); } if ((result & ClasspathChange.HAS_PROJECT_CHANGE) != 0) { - this.state.addProjectReferenceChange(change.project, change.oldResolvedClasspath); + change.project.getProject().clearCachedDynamicReferences(); + this.state.addProjectReferenceChange(change.project); } if ((result & ClasspathChange.HAS_LIBRARY_CHANGE) != 0) { this.state.addExternalFolderChange(change.project, change.oldResolvedClasspath); @@ -2145,20 +2146,13 @@ public class DeltaProcessor { } // update project references if necessary - ProjectReferenceChange[] projectRefChanges = this.state.removeProjectReferenceChanges(); - if (projectRefChanges != null) { - for (int i = 0, length = projectRefChanges.length; i < length; i++) { - try { - projectRefChanges[i].updateProjectReferencesIfNecessary(); - } catch(JavaModelException e) { - // project doesn't exist any longer, continue with next one - if (!e.isDoesNotExist()) - Util.log(e, "Exception while updating project references"); //$NON-NLS-1$ - } - } - } + Set<IJavaProject> referencedProjects = this.state.removeProjectReferenceChanges(); + needCycleValidation = needCycleValidation || !referencedProjects.isEmpty(); - if (needCycleValidation || projectRefChanges != null) { + if (needCycleValidation) { + for (IJavaProject next : referencedProjects) { + next.getProject().clearCachedDynamicReferences(); + } // update all cycle markers since the project references changes may have affected cycles try { JavaProject.validateCycles(null); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DynamicProjectReferences.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DynamicProjectReferences.java new file mode 100644 index 0000000000..41e63ea6ed --- /dev/null +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DynamicProjectReferences.java @@ -0,0 +1,31 @@ +package org.eclipse.jdt.internal.core; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IDynamicReferenceProvider; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; + +public class DynamicProjectReferences implements IDynamicReferenceProvider { + @Override + public List<IProject> getDependentProjects(IBuildConfiguration buildConfiguration) throws CoreException { + IProject input = buildConfiguration.getProject(); + IJavaProject javaProject = JavaCore.create(input); + if (javaProject instanceof JavaProject) { + JavaProject project = (JavaProject) javaProject; + + String[] required = project.projectPrerequisites(project.getResolvedClasspath()); + + IWorkspaceRoot wksRoot = input.getWorkspace().getRoot(); + return Arrays.stream(required).sorted().map(name -> wksRoot.getProject(name)).collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java deleted file mode 100644 index 548f383940..0000000000 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.core; - -import java.util.HashSet; -import java.util.Iterator; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IProjectDescription; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.IWorkspaceRunnable; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.internal.core.util.Util; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ProjectReferenceChange { - - private JavaProject project; - private IClasspathEntry[] oldResolvedClasspath; - - public ProjectReferenceChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) { - this.project = project; - this.oldResolvedClasspath = oldResolvedClasspath; - } - - /* - * Update projects references so that the build order is consistent with the classpath - */ - public void updateProjectReferencesIfNecessary() throws JavaModelException { - - String[] oldRequired = this.oldResolvedClasspath == null ? CharOperation.NO_STRINGS : this.project.projectPrerequisites(this.oldResolvedClasspath); - IClasspathEntry[] newResolvedClasspath = this.project.getResolvedClasspath(); - String[] newRequired = this.project.projectPrerequisites(newResolvedClasspath); - final IProject projectResource = this.project.getProject(); - - try { - IProject[] projectReferences = projectResource.getDescription().getDynamicReferences(); - - HashSet oldReferences = new HashSet(projectReferences.length); - for (int i = 0; i < projectReferences.length; i++){ - String projectName = projectReferences[i].getName(); - oldReferences.add(projectName); - } - HashSet newReferences = (HashSet)oldReferences.clone(); - - for (int i = 0; i < oldRequired.length; i++){ - String projectName = oldRequired[i]; - newReferences.remove(projectName); - } - for (int i = 0; i < newRequired.length; i++){ - String projectName = newRequired[i]; - newReferences.add(projectName); - } - - Iterator iter; - int newSize = newReferences.size(); - - checkIdentity: { - if (oldReferences.size() == newSize){ - iter = newReferences.iterator(); - while (iter.hasNext()){ - if (!oldReferences.contains(iter.next())){ - break checkIdentity; - } - } - return; - } - } - String[] requiredProjectNames = new String[newSize]; - int index = 0; - iter = newReferences.iterator(); - while (iter.hasNext()){ - requiredProjectNames[index++] = (String)iter.next(); - } - Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent - - final IProject[] requiredProjectArray = new IProject[newSize]; - IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot(); - for (int i = 0; i < newSize; i++){ - requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]); - } - - // ensure that a scheduling rule is used so that the project description is not modified by another thread while we update it - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=214981 - // also ensure that if no change (checkIdentify block returned above) we don't reach here - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=241751 - IWorkspace workspace = projectResource.getWorkspace(); - ISchedulingRule rule = workspace.getRuleFactory().modifyRule(projectResource); // scheduling rule for modifying the project - IWorkspaceRunnable runnable = new IWorkspaceRunnable() { - public void run(IProgressMonitor monitor) throws CoreException { - IProjectDescription description = projectResource.getDescription(); - description.setDynamicReferences(requiredProjectArray); - projectResource.setDescription(description, IResource.AVOID_NATURE_CONFIG, null); - } - }; - workspace.run(runnable, rule, IWorkspace.AVOID_UPDATE, null); - } catch(CoreException e){ - if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(this.project.getElementName())) - throw new JavaModelException(e); - } - } - public String toString() { - return "ProjectRefenceChange: " + this.project.getElementName(); //$NON-NLS-1$ - } -} diff --git a/org.eclipse.jdt.core/plugin.xml b/org.eclipse.jdt.core/plugin.xml index 76e3e99149..318c37352f 100644 --- a/org.eclipse.jdt.core/plugin.xml +++ b/org.eclipse.jdt.core/plugin.xml @@ -101,6 +101,7 @@ <builder> <run class="org.eclipse.jdt.internal.core.builder.JavaBuilder"> </run> + <dynamicReference class="org.eclipse.jdt.internal.core.DynamicProjectReferences"/> </builder> </extension> |