blob: b7347915e688c25149aca9f21ed57408310dde34 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2005, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.core;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImIdentitySet;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.preferences.PreferencesManageListener;
import org.eclipse.statet.ecommons.preferences.core.PreferenceAccess;
import org.eclipse.statet.ecommons.preferences.core.PreferenceSetService;
import org.eclipse.statet.ecommons.resources.core.AbstractProjectNature;
import org.eclipse.statet.ecommons.resources.core.BuildUtils;
import org.eclipse.statet.ecommons.resources.core.ProjectUtils;
import org.eclipse.statet.ltk.buildpaths.core.IBuildpathElement;
import org.eclipse.statet.r.core.RCodeStyleSettings;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.core.RProject;
import org.eclipse.statet.r.core.RProjects;
import org.eclipse.statet.r.core.renv.IREnvManager;
import org.eclipse.statet.rj.renv.core.REnv;
import org.eclipse.statet.rj.renv.core.REnvUtils;
@NonNullByDefault
public class RProjectNature extends AbstractProjectNature implements RProject, PreferenceSetService.ChangeListener {
public static final String OLD_QUALIFIER= "de.walware.r.core/RProjectBuild"; //$NON-NLS-1$
public static final String RPKG_ROOT_FOLDER_PATH_KEY= "RPkgRootFolder.path"; //$NON-NLS-1$
public static final String RENV_CODE_KEY= "REnv.code"; //$NON-NLS-1$
private static final ImIdentitySet<String> PREF_QUALIFIERS= ImCollections.newIdentitySet(
IREnvManager.PREF_QUALIFIER,
BUILD_PREF_QUALIFIER );
public static @Nullable RProjectNature getRProject(final @Nullable IProject project) {
try {
return (project != null) ? (RProjectNature) project.getNature(RProjects.R_NATURE_ID) : null;
}
catch (final CoreException e) {
RCorePlugin.log(e.getStatus());
return null;
}
}
private @Nullable String rPkgName;
private PreferencesManageListener preferenceListener;
private RCodeStyleSettings rCodeStyle;
private @Nullable REnv rEnv;
private RBuildpathPrefs rBuildpathPrefs;
private ImList<IBuildpathElement> rRawBuildpath;
@SuppressWarnings("null")
public RProjectNature() {
super();
}
@Override
public void setProject(final IProject project) {
super.setProject(project);
addPreferenceSetListener(this, PREF_QUALIFIERS);
updateREnv();
this.rCodeStyle= new RCodeStyleSettings(1);
this.preferenceListener= new PreferencesManageListener(this.rCodeStyle, getPrefs(),
RCodeStyleSettings.ALL_GROUP_IDS );
this.rBuildpathPrefs= new RBuildpathPrefs(getProjectContext(), BUILD_PREF_QUALIFIER,
getProject() );
updateBuildpath();
this.rPkgName= RCorePlugin.getInstance().getRModelManager().getIndex()
.getPkgName(project.getName());
RCorePlugin.getInstance().getResourceTracker().register(project, this);
}
@Override
public void dispose() {
RCorePlugin.getInstance().getResourceTracker().unregister(getProject());
super.dispose();
if (this.preferenceListener != null) {
this.preferenceListener.dispose();
this.preferenceListener= null;
}
this.rEnv= null;
}
@Override
public void deconfigure() throws CoreException {
dispose();
super.deconfigure();
}
@Override
public void addBuilders() throws CoreException {
final IProject project= getProject();
final IProjectDescription description= project.getDescription();
boolean changed= false;
changed|= ProjectUtils.addBuilder(description, RSupportBuilder.ID);
if (changed) {
project.setDescription(description, null);
}
}
@Override
public void removeBuilders() throws CoreException {
final IProject project= getProject();
final IProjectDescription description= project.getDescription();
boolean changed= false;
changed|= ProjectUtils.removeBuilder(description, RSupportBuilder.ID);
if (changed) {
project.setDescription(description, null);
}
}
@Override
public void preferenceChanged(final PreferenceSetService.ChangeEvent event) {
boolean clean= false;
if (event.contains(IREnvManager.PREF_QUALIFIER)
|| event.contains(RProject.RENV_CODE_PREF) ) {
updateREnv();
}
if (event.contains(RProject.BUILD_PREF_QUALIFIER, RBuildpathPrefs.STAMP_KEY)) {
updateBuildpath();
clean= true;
}
if (event.contains(RProject.PKG_BASE_FOLDER_PATH_PREF)) {
clean= true;
}
if (clean) {
BuildUtils.getCleanJob(getProject(), false).schedule();
}
}
private void updateREnv() {
final IREnvManager rEnvManager= RCore.getREnvManager();
final String s= getProjectValue(RProject.RENV_CODE_PREF);
this.rEnv= (s != null) ? REnvUtils.decode(s, rEnvManager) : rEnvManager.getDefault();
}
private void updateBuildpath() {
final ImList<IBuildpathElement> rawBuildpath= this.rBuildpathPrefs.load();
synchronized (this) {
this.rRawBuildpath= rawBuildpath;
}
}
@Override
public PreferenceAccess getPrefs() {
return this;
}
@Override
public @Nullable REnv getREnv() {
return this.rEnv;
}
@Override
public RCodeStyleSettings getRCodeStyle() {
return this.rCodeStyle;
}
@Override
public @Nullable IPath getPkgRootPath() {
final IProject project= getProject();
try {
if (project.hasNature(RProjects.R_PKG_NATURE_ID)) {
final IPath projectPath= getProject().getFullPath();
final String s= getPreferenceValue(RProject.PKG_BASE_FOLDER_PATH_PREF);
if (s != null) {
return projectPath.append(Path.fromPortableString(s));
}
return projectPath;
}
}
catch (final CoreException e) {
}
return null;
}
@Override
public ImList<IBuildpathElement> getRawBuildpath() {
return this.rRawBuildpath;
}
@Override
public @Nullable String getPkgName() {
return this.rPkgName;
}
/**
* Called by project builder
*
* @param pkgName
*/
public void updateRPkgConfig(final @Nullable String pkgName) {
final boolean changed= (pkgName != null) != (this.rPkgName != null);
this.rPkgName= pkgName;
if (changed) {
// checkPackageNature();
}
}
public void saveBuildpath(final ImList<IBuildpathElement> rawBuildpath) {
if (getRawBuildpath().equals(rawBuildpath)) {
return;
}
this.rBuildpathPrefs.save(rawBuildpath, true);
}
}