Skip to content

Commit

Permalink
Let ProjectNatureUpdater always override if model is present
Browse files Browse the repository at this point in the history
This ensures that the Eclipse project faithfully matches the Gradle
project. If the Gradle version does not provide project nature
information, then the user-defined natures stay untouched.
  • Loading branch information
oehme authored and donat committed Dec 4, 2016
1 parent 10cc210 commit f515066
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 89 deletions.
@@ -1,6 +1,8 @@
package org.eclipse.buildship.core.workspace.internal

import org.gradle.api.JavaVersion
import spock.lang.Ignore;

import org.eclipse.buildship.core.CorePlugin
import org.eclipse.buildship.core.configuration.GradleProjectNature
import org.eclipse.buildship.core.configuration.internal.ProjectConfigurationPersistence
Expand Down Expand Up @@ -58,6 +60,7 @@ class ImportingProjectWithExistingDescriptor extends SingleProjectSynchronizatio
!project.getFile(".classpath").exists()
}

@Ignore("We will remove the whole merge feature soon")
def "If the project descriptor is merged on import, then existing settings are kept"() {
setup:
IProject project = newJavaProject('sample-project').project
Expand Down
Expand Up @@ -26,6 +26,28 @@ class ProjectNatureUpdaterTest extends WorkspaceSpecification {
project.description.natureIds.find{ it == 'org.eclipse.pde.UpdateSiteNature' }
}

def "Gradle Nature is added when nature information is present"() {
given:
def project = newProject('sample-project')

when:
ProjectNatureUpdater.update(project, natures(), new NullProgressMonitor())

then:
project.description.natureIds.find{ it == GradleProjectNature.ID }
}

def "Gradle Nature is added when nature information is absent"() {
given:
def project = newProject('sample-project')

when:
ProjectNatureUpdater.update(project, Optional.absent(), new NullProgressMonitor())

then:
project.description.natureIds.find{ it == GradleProjectNature.ID }
}

def "Project natures are removed if they no longer exist in the Gradle model"() {
given:
def project = newProject('sample-project')
Expand All @@ -39,30 +61,29 @@ class ProjectNatureUpdaterTest extends WorkspaceSpecification {
project.description.natureIds.find{ it == 'org.eclipse.jdt.core.javanature' }
}

def "Manually added natures are preserved"() {
def "Manually added natures are preserved if Gradle model has no nature information"() {
given:
def project = newProject('sample-project')
def description = project.description
description.setNatureIds(['org.eclipse.pde.UpdateSiteNature'] as String[])
def manualNatures = ['org.eclipse.pde.UpdateSiteNature', 'org.eclipse.jdt.core.javanature']
description.setNatureIds(manualNatures as String[])
project.setDescription(description, new NullProgressMonitor())

when:
ProjectNatureUpdater.update(project, natures(), new NullProgressMonitor())
ProjectNatureUpdater.update(project, Optional.absent(), new NullProgressMonitor())

then:
project.description.natureIds.find{ it == 'org.eclipse.pde.UpdateSiteNature' }
project.description.natureIds as List == manualNatures + [GradleProjectNature.ID]
}

def "Project natures that were previously defined manually are transformed to model source folders"() {
def "Manually added natures are removed if Gradle model has nature information"() {
given:
def project = newProject('sample-project')
def description = project.description
description.setNatureIds([
'org.eclipse.pde.UpdateSiteNature'] as String[])
description.setNatureIds(['org.eclipse.pde.UpdateSiteNature'] as String[])
project.setDescription(description, new NullProgressMonitor())

when:
ProjectNatureUpdater.update(project, natures('org.eclipse.pde.UpdateSiteNature'), new NullProgressMonitor())
ProjectNatureUpdater.update(project, natures(), new NullProgressMonitor())

then:
Expand Down
Expand Up @@ -12,110 +12,53 @@
package org.eclipse.buildship.core.workspace.internal;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import com.gradleware.tooling.toolingmodel.OmniEclipseProjectNature;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;

import org.eclipse.buildship.core.CorePlugin;
import org.eclipse.buildship.core.configuration.GradleProjectNature;

/**
* Updates the natures on the target project.
*/
final class ProjectNatureUpdater {

private static final String PROJECT_PROPERTY_KEY_GRADLE_NATURES = "natures";

private final IProject project;
private final ImmutableList<OmniEclipseProjectNature> natures;

public ProjectNatureUpdater(IProject project, List<OmniEclipseProjectNature> natures) {
this.project = Preconditions.checkNotNull(project);
this.natures = ImmutableList.copyOf(natures);
}

private void updateNatures(IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 2);
StringSetProjectProperty knownNatures = StringSetProjectProperty.from(this.project, PROJECT_PROPERTY_KEY_GRADLE_NATURES);
removeNaturesRemovedFromGradleModel(knownNatures, progress.newChild(1));
addNaturesNewInGradleModel(knownNatures, progress.newChild(1));
}

private void addNaturesNewInGradleModel(StringSetProjectProperty knownNatures, SubMonitor progress) throws CoreException {
Set<String> newNatureNames = Sets.newLinkedHashSet();
for (OmniEclipseProjectNature nature : this.natures) {
String natureId = nature.getId();
if (natureRecognizedByEclipse(natureId)) {
newNatureNames.add(natureId);
}
}
addNatures(this.project, newNatureNames, progress);
knownNatures.set(newNatureNames);
}

private void addNatures(IProject project, Set<String> natureIds, SubMonitor progress) throws CoreException {
public static void update(IProject project, Optional<List<OmniEclipseProjectNature>> projectNatures, IProgressMonitor monitor) throws CoreException {
IProjectDescription description = project.getDescription();

Set<String> newIds = Sets.newLinkedHashSet(Arrays.asList(description.getNatureIds()));
newIds.addAll(natureIds);

description.setNatureIds(newIds.toArray(new String[0]));
project.setDescription(description, progress);
Set<String> natures = toNatures(projectNatures, description);
description.setNatureIds(natures.toArray(new String[0]));
project.setDescription(description, monitor);
}

private boolean natureRecognizedByEclipse(String natureId) {
return ResourcesPlugin.getWorkspace().getNatureDescriptor(natureId) != null;
}

private void removeNaturesRemovedFromGradleModel(StringSetProjectProperty knownNatures, SubMonitor progress) throws CoreException {
Set<String> knownNatureIds = knownNatures.get();
Set<String> naturesToRemove = Sets.newLinkedHashSet();
for (String knownNatureId : knownNatureIds) {
if (!natureIdExistsInGradleModel(knownNatureId)) {
naturesToRemove.add(knownNatureId);
}
private static Set<String> toNatures(Optional<List<OmniEclipseProjectNature>> projectNatures, IProjectDescription description) {
Set<String> natures = Sets.newLinkedHashSet();
if (projectNatures.isPresent()) {
natures.addAll(toNatures(projectNatures.get()));
} else {
natures.addAll(Arrays.asList(description.getNatureIds()));
}
removeNatures(this.project, naturesToRemove, progress);
}

private void removeNatures(IProject project, Set<String> natureIds, SubMonitor progress) throws CoreException {
IProjectDescription description = project.getDescription();

List<String> newIds = Lists.newArrayList(description.getNatureIds());
newIds.removeAll(natureIds);

description.setNatureIds(newIds.toArray(new String[0]));
project.setDescription(description, progress);
natures.add(GradleProjectNature.ID);
return natures;
}

private boolean natureIdExistsInGradleModel(final String natureId) {
return FluentIterable.from(this.natures).firstMatch(new Predicate<OmniEclipseProjectNature>() {

@Override
public boolean apply(OmniEclipseProjectNature nature) {
return nature.getId().equals(natureId);
private static Set<? extends String> toNatures(List<OmniEclipseProjectNature> projectNatures) {
Set<String> natures = Sets.newLinkedHashSet();
for (OmniEclipseProjectNature projectNature : projectNatures) {
String id = projectNature.getId();
if (CorePlugin.workspaceOperations().isNatureRecognizedByEclipse(id)) {
natures.add(id);
}
}).isPresent();
}

public static void update(IProject project, Optional<List<OmniEclipseProjectNature>> projectNatures, IProgressMonitor monitor) throws CoreException {
List<OmniEclipseProjectNature> natures = projectNatures.or(Collections.<OmniEclipseProjectNature>emptyList());
ProjectNatureUpdater updater = new ProjectNatureUpdater(project, natures);
updater.updateNatures(monitor);
}
return natures;
}

}
Expand Up @@ -69,7 +69,6 @@
* <li>If the workspace project is open:
* <ul>
* <li>the project name is updated</li>
* <li>the Gradle nature is set</li>
* <li>the Gradle settings file is written</li>
* <li>the linked resources are set</li>
* <li>the derived resources are marked</li>
Expand Down

0 comments on commit f515066

Please sign in to comment.