From a0a2059fdd2296fe9fd9c269e129d24fe9b9bf48 Mon Sep 17 00:00:00 2001 From: Andrew Eidsness Date: Tue, 10 Sep 2013 21:33:19 -0400 Subject: [PATCH] Bug 416471: Support for extra ILanguageSettingsProviders in new projects This change introduces three new ProcessRunners that can be used in the New Project wizard's template.xml files. These will be used by two new Qt project wizards that I will introduce in a second patch. The three new rules are: 1) "AddMakeTarget" which creates new Make Targets (in the Make Targets view) for the new projects. 2) "SetEnvironmentVariable" which sets an environment variable in all of the new project's build configurations. 3) "ExtraLanguageSettingsProvider" which modifies the new project's build configurations to include a new ILanguageSettingsProvider. The first two are straightforward, the third is a bit different. Instead of creating a new Toolchain or Configuration it modifies the Configurations that were created for the new project. In this case the only modification is to add the extra ILanguageSettingsProvider, but it might be useful to extend this to other customizations as well. Change-Id: I30710400e9b0dffcbe6e8965ce7ce2078c1c99ca Signed-off-by: Andrew Eidsness Reviewed-on: https://git.eclipse.org/r/16817 Reviewed-by: Andrew Gvozdev IP-Clean: Andrew Gvozdev Tested-by: Andrew Gvozdev --- build/org.eclipse.cdt.make.core/plugin.xml | 12 ++ .../core/templateengine/AddMakeTarget.java | 99 +++++++++++++++ .../plugin.xml | 6 + .../AddLanguageSettingsProvider.java | 94 +++++++++++++++ core/org.eclipse.cdt.core/plugin.xml | 11 ++ .../TemplateEngineMessages.java | 5 + .../core/templateengine/messages.properties | 1 + .../templateengine/process/ProcessRunner.java | 21 +++- .../processes/SetEnvironmentVariable.java | 114 ++++++++++++++++++ 9 files changed, 357 insertions(+), 6 deletions(-) create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/templateengine/AddMakeTarget.java create mode 100644 build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/templateengine/processes/AddLanguageSettingsProvider.java create mode 100644 core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/processes/SetEnvironmentVariable.java diff --git a/build/org.eclipse.cdt.make.core/plugin.xml b/build/org.eclipse.cdt.make.core/plugin.xml index 36067e63368..2eded824313 100644 --- a/build/org.eclipse.cdt.make.core/plugin.xml +++ b/build/org.eclipse.cdt.make.core/plugin.xml @@ -183,4 +183,16 @@ /> + + + + + + + + + + diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/templateengine/AddMakeTarget.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/templateengine/AddMakeTarget.java new file mode 100644 index 00000000000..b8e59f98b21 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/templateengine/AddMakeTarget.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2013 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.templateengine; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.process.ProcessArgument; +import org.eclipse.cdt.core.templateengine.process.ProcessFailureException; +import org.eclipse.cdt.core.templateengine.process.ProcessRunner; +import org.eclipse.cdt.make.core.IMakeCommonBuildInfo; +import org.eclipse.cdt.make.core.IMakeTarget; +import org.eclipse.cdt.make.core.IMakeTargetManager; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * A step that can be used by the New Project template.xml file to add make targets to + * newly created C/C++ projects. E.g., + *
+ *  <process type="org.eclipse.cdt.make.core.AddMakeTarget">
+ *      <simple name="projectName" value="$(projectName)"/>
+ *      <simple name="targetName" value="build-debug"/>
+ *      <simple name="makeTarget" value="debug"/>
+ *  </process>
+ * 
+ * The rule's parameters are used to populate fields in the "Create|Modify Make Target" + * dialog box (which is opened from the Make Target view). The two mandatory parameters + * are projectName and targetName. There are also three optional parameters: + *

+ * makeTarget: The name of the make target to run, defaults to targetName
+ * buildCommand: The build command to execute, e.g., "make"
+ * buildArguments: The arguments that should be passed to the build command, e.g., "-s"
+ */ +public class AddMakeTarget extends ProcessRunner { + + private static final String BUILDER_ID = "org.eclipse.cdt.build.MakeTargetBuilder"; //$NON-NLS-1$ + + private static final String PROJECTNAME_VARNAME = "projectName"; //$NON-NLS-1$ + private static final String TARGETNAME_VARNAME = "targetName"; //$NON-NLS-1$ + private static final String MAKETARGET_VARNAME = "makeTarget"; //$NON-NLS-1$ + private static final String BUILDCOMMAND_VARNAME = "buildCommand"; //$NON-NLS-1$ + private static final String BUILDARGUMENTS_COMMAND_VARNAME = "buildArguments"; //$NON-NLS-1$ + + private static final String BUILDCOMMAND_DEFAULT = "make"; //$NON-NLS-1$ + private static final String BUILDARGUMENTS_DEFAULT = ""; //$NON-NLS-1$ + + @Override + public void process(TemplateCore template, ProcessArgument[] args, String processId, IProgressMonitor monitor) throws ProcessFailureException { + IProject project = null; + String targetName = null; + String makeTarget = null; + String buildCommand = null; + String buildArguments = null; + + for (ProcessArgument arg : args) { + String argName = arg.getName(); + if (PROJECTNAME_VARNAME.equals(argName)) + project = ResourcesPlugin.getWorkspace().getRoot().getProject(arg.getSimpleValue()); + else if (TARGETNAME_VARNAME.equals(argName)) + targetName = arg.getSimpleValue(); + else if (MAKETARGET_VARNAME.equals(argName)) + makeTarget = arg.getSimpleValue(); + else if (BUILDCOMMAND_VARNAME.equals(argName)) + buildCommand = arg.getSimpleValue(); + else if(BUILDARGUMENTS_COMMAND_VARNAME.equals(argName)) + buildArguments = arg.getSimpleValue(); + } + + if (project == null) + throw missingArgException(processId, PROJECTNAME_VARNAME); + if (targetName == null) + throw missingArgException(processId, TARGETNAME_VARNAME); + + IMakeTargetManager makeTargetManager = MakeCorePlugin.getDefault().getTargetManager(); + try { + IMakeTarget target = makeTargetManager.createTarget(project, targetName, BUILDER_ID); + + target.setBuildAttribute(IMakeTarget.BUILD_TARGET, makeTarget == null ? targetName : makeTarget); + + target.setUseDefaultBuildCmd(buildCommand == null); + target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, buildCommand == null ? BUILDCOMMAND_DEFAULT : buildCommand); + target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, buildArguments == null ? BUILDARGUMENTS_DEFAULT : buildArguments); + + makeTargetManager.addTarget(target); + } catch(CoreException e) { + throw new ProcessFailureException(e); + } + } +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml index 63665251f2a..4498dcd9498 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml @@ -584,6 +584,12 @@ processRunner="org.eclipse.cdt.managedbuilder.templateengine.processes.GenerateMakefileWithBuildDescription"> + + + + + <process type="org.eclipse.cdt.managedbuilder.core.AddLanguageSettingsProvider"> + <simple name="projectName" value="$(projectName)"/> + <simple-array name="languageSettingsProviders"> + <element value="org.eclipse.cdt.qt.core.QtPathsProvider"/> + </simple-array> + </process> + * + * + * @since 8.3 + */ +public class AddLanguageSettingsProvider extends ProcessRunner { + + private static final String PROJECTNAME_VARNAME = "projectName"; //$NON-NLS-1$ + private static final String PROVIDERS_VARNAME = "languageSettingsProviderIds"; //$NON-NLS-1$ + + @Override + public void process(TemplateCore template, ProcessArgument[] args, String processId, IProgressMonitor monitor) throws ProcessFailureException { + IProject project = null; + String[] extraProviderIds = null; + + for (ProcessArgument arg : args) { + String argName = arg.getName(); + if (PROJECTNAME_VARNAME.equals(argName)) + project = ResourcesPlugin.getWorkspace().getRoot().getProject(arg.getSimpleValue()); + else if(PROVIDERS_VARNAME.equals(argName)) + extraProviderIds = arg.getSimpleArrayValue(); + } + + if (project == null) + throw missingArgException(processId, PROJECTNAME_VARNAME); + if (extraProviderIds == null) + throw missingArgException(processId, PROVIDERS_VARNAME); + + ICProjectDescriptionManager mngr = CoreModel.getDefault().getProjectDescriptionManager(); + ICProjectDescription des = mngr.getProjectDescription(project, true); + ICConfigurationDescription[] configDescs = des.getConfigurations(); + + for (ICConfigurationDescription configDesc : configDescs) + if (configDesc instanceof ILanguageSettingsProvidersKeeper) { + IConfiguration config = ManagedBuildManager.getConfigurationForDescription(configDesc); + + // Create a merged array of the old and new ids + String[] ids = config.getDefaultLanguageSettingsProviderIds(); + String[] newIds = new String[ids.length + extraProviderIds.length]; + System.arraycopy(ids, 0, newIds, 0, ids.length); + System.arraycopy(extraProviderIds, 0, newIds, ids.length, extraProviderIds.length); + + ILanguageSettingsProvidersKeeper keeper = (ILanguageSettingsProvidersKeeper) configDesc; + keeper.setLanguageSettingProviders(LanguageSettingsManager.createLanguageSettingsProviders(newIds)); + } + + try { + mngr.setProjectDescription(project, des); + } catch(CoreException e) { + ManagedBuilderCorePlugin.log(e); + } + } +} diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index 235bd075aca..0d4bbd6b960 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -782,6 +782,17 @@ name="natureId"> + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/TemplateEngineMessages.java b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/TemplateEngineMessages.java index bba96d27340..4f790d97909 100644 --- a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/TemplateEngineMessages.java +++ b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/TemplateEngineMessages.java @@ -19,6 +19,11 @@ public class TemplateEngineMessages { private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); + /** + * @since 5.6 + */ + public static String ProcessRunner_missingArg; + private TemplateEngineMessages() { } diff --git a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/messages.properties b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/messages.properties index 08d89dd50bf..43bd4b7692d 100644 --- a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/messages.properties +++ b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/messages.properties @@ -30,3 +30,4 @@ ProcessRunner.error=-->Error: ProcessRunner.success=-->Success: ProcessRunner.info=-->Info: ProcessHelper.fileNotFound=File not found: ''{0}'' +ProcessRunner_missingArg = ILanguageSettingsProvider failure: argument {0} not found diff --git a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/ProcessRunner.java b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/ProcessRunner.java index b091e0ae16b..b2742a9bf43 100644 --- a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/ProcessRunner.java +++ b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/ProcessRunner.java @@ -15,25 +15,34 @@ import org.eclipse.cdt.core.templateengine.TemplateEngineMessages; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import com.ibm.icu.text.MessageFormat; /** * Abstract ProcessRunner class provides the methods to implement for processes. */ public abstract class ProcessRunner { - + private ProcessParameter[] params = new ProcessParameter[0]; - + void setProcessParameters(ProcessParameter[] params) { this.params = params == null ? new ProcessParameter[0] : params; } - + /** * Returns the Process Parameters. */ public ProcessParameter[] getProcessParameters() { return params; } - + + /** + * @since 5.6 + */ + protected ProcessFailureException missingArgException(String processId, String varname) { + String msg = MessageFormat.format(TemplateEngineMessages.ProcessRunner_missingArg, varname); + return new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR, msg)); + } + /** * Checks the whether the arguments are matching the required parameters. */ @@ -54,7 +63,7 @@ public abstract class ProcessRunner { } return true; } - + /** * Return the String containing the mismatching message * if the arguments are not matching the required parameters. @@ -95,7 +104,7 @@ public abstract class ProcessRunner { return processId + TemplateEngineMessages.getString("ProcessRunner.info") + msg; //$NON-NLS-1$ } } - + /** * @param template * @param args diff --git a/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/processes/SetEnvironmentVariable.java b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/processes/SetEnvironmentVariable.java new file mode 100644 index 00000000000..3492ff706ab --- /dev/null +++ b/core/org.eclipse.cdt.core/templateengine/org/eclipse/cdt/core/templateengine/process/processes/SetEnvironmentVariable.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2013 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.templateengine.process.processes; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.envvar.IContributedEnvironment; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager; +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.process.ProcessArgument; +import org.eclipse.cdt.core.templateengine.process.ProcessFailureException; +import org.eclipse.cdt.core.templateengine.process.ProcessRunner; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * A template process for setting an environment variable in all of the new project's + * build configurations. E.g., + *

+ *  <process type="org.eclipse.cdt.core.SetEnvironmentVariable">
+ *      <simple name="projectName" value="$(projectName)"/>
+ *      <complex-array name="variables">
+ *          <element>
+ *              <simple name="name" value="QMAKE"/>
+ *              <simple name="value" value="$(qmake)"/>
+ *          </element>
+ *      </complex-array>
+ *  </process>
+ * 
+ * This will create an environment variable called "QMAKE" and will set the value to + * be the value entered in a field (called qmake) in the New Project wizard. + * + * @since 5.6 + */ +public class SetEnvironmentVariable extends ProcessRunner { + + private static final String PROJECTNAME_VARNAME = "projectName"; //$NON-NLS-1$ + private static final String VARIABLES_VARNAME = "variables"; //$NON-NLS-1$ + private static final String VARIABLES_NAME_VARNAME = "name"; //$NON-NLS-1$ + private static final String VARIABLES_VALUE_VARNAME = "value"; //$NON-NLS-1$ + + @Override + public void process(TemplateCore template, ProcessArgument[] args, String processId, IProgressMonitor monitor) throws ProcessFailureException { + + IProject project = null; + Map envVars = new LinkedHashMap(); + + for (ProcessArgument arg : args) { + String argName = arg.getName(); + if (PROJECTNAME_VARNAME.equals(argName)) + project = ResourcesPlugin.getWorkspace().getRoot().getProject(arg.getSimpleValue()); + else if(VARIABLES_VARNAME.equals(argName)) { + + for(ProcessArgument[] envVarArgs : arg.getComplexArrayValue()) { + String name = null; + String value = null; + + for(ProcessArgument varArg : envVarArgs) { + String varArgName = varArg.getName(); + if (VARIABLES_NAME_VARNAME.equals(varArgName)) + name = varArg.getSimpleValue(); + else if(VARIABLES_VALUE_VARNAME.equals(varArgName)) + value = varArg.getSimpleValue(); + } + + if (name == null) + throw missingArgException(processId, VARIABLES_NAME_VARNAME); + if (value == null) + throw missingArgException(processId, VARIABLES_VALUE_VARNAME); + + envVars.put(name, value); + } + } + } + + if (project == null) + throw missingArgException(processId, PROJECTNAME_VARNAME); + + ICProjectDescriptionManager mngr = CoreModel.getDefault().getProjectDescriptionManager(); + ICProjectDescription des = mngr.getProjectDescription(project, true); + ICConfigurationDescription[] configDescs = des.getConfigurations(); + IContributedEnvironment ice = CCorePlugin.getDefault().getBuildEnvironmentManager().getContributedEnvironment(); + + for(Map.Entry envVar : envVars.entrySet()) { + String name = envVar.getKey(); + String value = envVar.getValue(); + + for (ICConfigurationDescription configDesc : configDescs) + ice.addVariable(name, value, IEnvironmentVariable.ENVVAR_REPLACE, null, configDesc); + } + + try { + mngr.setProjectDescription(project, des); + } catch(CoreException e) { + CCorePlugin.log(e); + } + } +}