Bug 486232, Bug 486233 - Adding Launch Configurations for Grunt/Gulp

Change-Id: I403696e6719dc4d45c31b50c72bb83f17e3d161c
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
diff --git a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/Messages.java b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/Messages.java
index 7b31ec8..21a4f9b 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/Messages.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/Messages.java
@@ -26,6 +26,7 @@
 	public static String LaunchTab_Browse;
 	public static String LaunchTab_DialogTitle;
 	public static String LaunchTab_DialogMessage;
+	public static String LaunchTab_Parameters;
 	
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/LaunchConfigurationAutoFill.java b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/LaunchConfigurationAutoFill.java
index 9f4fc90..6c35ae5 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/LaunchConfigurationAutoFill.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/LaunchConfigurationAutoFill.java
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.wst.jsdt.js.common.build.system.launch;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.wst.jsdt.js.common.CommonPlugin;
@@ -19,20 +22,32 @@
  * @author "Ilya Buziuk (ibuziuk)"
  */
 public class LaunchConfigurationAutoFill {
-	
-	public static ILaunchConfiguration chooseLaunchConfiguration(ILaunchConfiguration[] configurations, ITask task, String attribute) {
+
+	/**
+	 * Filters configurations for launch configurations with the same build file as a task.
+	 *
+	 * @param configurations - the launch configurations to filter
+	 * @param task - the target task
+	 * @param buildAttribute - the name of the launch configuration attribute that stores the build file.
+	 * @return an array of launch configurations that target the same build file as task
+	 */
+	public static ILaunchConfiguration[] getAllLaunchConfigurations(
+			ILaunchConfiguration[] configurations, ITask task, String buildAttribute) {
+
+		List<ILaunchConfiguration> validConfigs = new ArrayList<>();
 		try {
 			for (ILaunchConfiguration conf : configurations) {
-				String buildFileAttribute = conf.getAttribute(attribute, (String) null);
+				String buildFileAttribute = conf.getAttribute(buildAttribute, (String) null);
 				String buildFilePath = task.getBuildFile().getLocation().toOSString();
 				// Launch Configuration per build file (i.e. Gruntfile.js / gulpfile.js)
 				if (buildFilePath.equals(buildFileAttribute)) {
-					return conf;
+					validConfigs.add(conf);
 				}
 			}
 		} catch (CoreException e) {
 			CommonPlugin.logError(e, e.getMessage());
 		}
-		return null;
+
+		return validConfigs.toArray(new ILaunchConfiguration[validConfigs.size()]);
 	}
 }
diff --git a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/ui/GenericBuildSystemTab.java b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/ui/GenericBuildSystemTab.java
index 9ab2374..703f940 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/ui/GenericBuildSystemTab.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/build/system/launch/ui/GenericBuildSystemTab.java
@@ -47,6 +47,7 @@
 	private WidgetListener defaultListener = new WidgetListener();
 	protected Text buildFileText;
 	protected Combo tasksCommbo;
+	protected Text parametersText;
 	
 	protected abstract String[] getTasksFromFile(IFile file) throws JavaScriptModelException;
 	
@@ -57,6 +58,7 @@
 		((GridLayout) comp.getLayout()).verticalSpacing = 0;		
 		createBuildFileEditor(comp);
 		createTaskComboEditor(comp);
+		createParametersText(comp);
 		setControl(comp);
 	}
 	
@@ -66,6 +68,12 @@
 		tasksCommbo.addModifyListener(defaultListener);
 	}
 
+	private void createParametersText(Composite parent) {
+		Group group = SWTFactory.createGroup(parent, Messages.LaunchTab_Parameters, 1, 1, GridData.FILL_HORIZONTAL);
+		parametersText = SWTFactory.createSingleText(group, 1);
+		parametersText.addModifyListener(defaultListener);
+	}
+
 	private void createBuildFileEditor(Composite parent) {
 		Group group = SWTFactory.createGroup(parent, Messages.LaunchTab_BuildFile, 2, 1, GridData.FILL_HORIZONTAL);
 		buildFileText = SWTFactory.createSingleText(group, 1);
diff --git a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/messages.properties b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/messages.properties
index 6069f69..21fb27b 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/messages.properties
+++ b/nodejs/org.eclipse.wst.jsdt.js.common/src/org/eclipse/wst/jsdt/js/common/messages.properties
@@ -14,5 +14,6 @@
 LaunchTab_DialogTitle=Build File
 LaunchTab_DialogMessage=Select a Build File
 LaunchTab_Browse=Browse
+LaunchTab_Parameters=Parameters
 LaunchError_Title=Error Occurred
 LaunchError_Message=Launch Error
\ No newline at end of file
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/GruntConstants.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/GruntConstants.java
index 1aca8c3..a25d932 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/GruntConstants.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/GruntConstants.java
@@ -26,8 +26,11 @@
 	public static final String DIR = GruntPlugin.PLUGIN_ID + ".DIR"; //$NON-NLS-1$
 	public static final String COMMAND = GruntPlugin.PLUGIN_ID + ".COMMAND"; //$NON-NLS-1$
 	public static final String BUILD_FILE = GruntPlugin.PLUGIN_ID + ".BUILD_FILE"; //$NON-NLS-1$
+	public static final String PARAMETERS = GruntPlugin.PLUGIN_ID + ".PARAMETERS"; //$NON-NLS-1$
 
 	public static final String GRUNT = "grunt"; //$NON-NLS-1$
 	public static final String GRUNT_FILE_JS = "gruntfile.js"; //$NON-NLS-1$
+	public static final String DEFAULT_COMMAND = "default"; //$NON-NLS-1$
+	public static final String GRUNT_NO_COLOR = "--no-color";
 
 }
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/Messages.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/Messages.java
index 7bbfd4a..4586cbc 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/Messages.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/Messages.java
@@ -22,6 +22,7 @@
 	public static String GruntLaunchError_Message;
 	public static String GruntLaunchTab_Main;
 	public static String GruntLaunchTab_ErrorNotExist;
+	public static String GruntLaunchTab_WarningTaskNotExist;
 	
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/GruntLaunchConfigurationDelegate.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/GruntLaunchConfigurationDelegate.java
index 2ac169e..7b668ef 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/GruntLaunchConfigurationDelegate.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/GruntLaunchConfigurationDelegate.java
@@ -34,11 +34,12 @@
 		String projectName = conf.getAttribute(GruntConstants.PROJECT, (String) null);
 		String dirPath = conf.getAttribute(GruntConstants.DIR, (String) null);
 		String commandName = conf.getAttribute(GruntConstants.COMMAND, (String) null);
+		String parameters = conf.getAttribute(GruntConstants.PARAMETERS, (String) null);
 		
 		IProject project = WorkbenchResourceUtil.getProject(projectName);
 		if (project != null && project.exists()) {
 			IPath dir = (dirPath == null) ? project.getLocation() : new Path(dirPath);
-			CLICommand command = generateCLICommand(commandName);
+			CLICommand command = generateCLICommand(commandName, parameters);
 			launchGrunt(project, dir, command, monitor);
 		}	
 	}
@@ -52,8 +53,10 @@
 		}
 	}
 	
-	protected CLICommand generateCLICommand(String commandName) {
-		return new CLICommand(GruntConstants.GRUNT, commandName, null, null);
+	protected CLICommand generateCLICommand(String commandName, String parameters) {
+		// ANSI color codes are not supported.
+		String[] options = {GruntConstants.GRUNT_NO_COLOR};
+		return new CLICommand(GruntConstants.GRUNT, commandName, parameters, options);
 	}
 
 }
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/shortcut/GruntLaunch.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/shortcut/GruntLaunch.java
index 0c0e796..79bd5ca 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/shortcut/GruntLaunch.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/shortcut/GruntLaunch.java
@@ -63,19 +63,22 @@
 			ILaunchConfiguration[] configurations = DebugPlugin.getDefault()
 					.getLaunchManager().getLaunchConfigurations(gruntLaunchConfiguraionType);
 			
-			ILaunchConfiguration existingConfiguraion = LaunchConfigurationAutoFill
-					.chooseLaunchConfiguration(configurations, task, GruntConstants.BUILD_FILE);
-			
-			if (existingConfiguraion != null) {
-				ILaunchConfigurationWorkingCopy wc = existingConfiguraion.getWorkingCopy();
-				// Updating task in the existing launch
-				wc.setAttribute(GruntConstants.COMMAND, task.getName());
-				existingConfiguraion = wc.doSave();
-				DebugUITools.launch(existingConfiguraion, mode);
-			// Creating Launch Configuration from scratch
-			} else if (buildFile != null){
+			// Get only configurations for this Gruntfile.
+			ILaunchConfiguration[] existingConfigurations = LaunchConfigurationAutoFill
+					.getAllLaunchConfigurations(configurations, task, GruntConstants.BUILD_FILE);
+
+			for (ILaunchConfiguration conf : existingConfigurations) {
+				if (conf.getAttribute(GruntConstants.COMMAND, (String) null).equals(task.getName())) {
+					DebugUITools.launch(conf, mode);
+					return;
+				}
+			}
+
+			// No configuration found; create a new one.
+			if (buildFile != null){
 				IProject project = buildFile.getProject();	
-				ILaunchConfigurationWorkingCopy newConfiguration = createEmptyLaunchConfiguration(project.getName() + " [" + buildFile.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				ILaunchConfigurationWorkingCopy newConfiguration = createEmptyLaunchConfiguration(
+						project.getName() + " - " + task.getName() + " [" + buildFile.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 				newConfiguration.setAttribute(GruntConstants.BUILD_FILE, buildFile.getLocation().toOSString());
 				newConfiguration.setAttribute(GruntConstants.PROJECT, project.getName());
 				newConfiguration.setAttribute(GruntConstants.DIR, buildFile.getParent().getLocation().toOSString());
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/ui/GruntLaunchTab.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/ui/GruntLaunchTab.java
index 4362737..aae6c5b 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/ui/GruntLaunchTab.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/launch/ui/GruntLaunchTab.java
@@ -11,6 +11,8 @@
 package org.eclipse.wst.jsdt.js.grunt.internal.launch.ui;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
@@ -38,6 +40,7 @@
 	@Override
 	public boolean isValid(ILaunchConfiguration launchConfig) {
 		setErrorMessage(null);
+		setWarningMessage(null);
 		
 		String buildFilePath = buildFileText.getText();
 		File file = WorkbenchResourceUtil.getFile(buildFilePath);
@@ -46,6 +49,26 @@
 			return false;
 		}
 		
+		// Check if the selected task exists in the Gruntfile, display warning if it does not.
+		try {
+			String task = tasksCommbo.getText();
+			if (task.isEmpty()) {
+				return true;
+			}
+			String rootTask = task.split(":")[0];
+			IFile ifile =  WorkbenchResourceUtil.getFileForLocation(file.getAbsolutePath());
+
+			List<String> availTasks = Arrays.asList(getTaskNames(
+					ASTUtil.getTasks(buildFilePath, new GruntVisitor(ifile))));
+
+			if (!availTasks.contains(rootTask)) {
+				setWarningMessage(Messages.GruntLaunchTab_WarningTaskNotExist);
+			}
+
+		} catch (JavaScriptModelException e) {
+			GruntPlugin.logError(e, e.getMessage());
+		}
+
 		return true;
 	}
 		
@@ -69,17 +92,28 @@
 				ifile = WorkbenchResourceUtil.getFileForLocation(file.getAbsolutePath());
 			}
 			
-			
+			// If launch config has a defined task, use that, if not use 'default'. If there is 
+			// no default, leave task field blank.
+			String task = lc.getAttribute(GruntConstants.COMMAND, (String) null);
 			Set<ITask> tasks = ASTUtil.getTasks(buildFileLocation, new GruntVisitor(ifile));
-			if (!tasks.isEmpty()) {
-				updateTasks(getTaskNames(tasks));
-				String task = lc.getAttribute(GruntConstants.COMMAND, (String) null);
-				if (task != null && tasks.contains(task)) {
-					tasksCommbo.setText(task);
+			List<String> tasknames = Arrays.asList(getTaskNames(tasks));
+			updateTasks(getTaskNames(tasks));
+			if (task != null && !task.isEmpty()) {
+				tasksCommbo.setText(task);
+			} else {
+				if (tasknames.contains(GruntConstants.DEFAULT_COMMAND)) {
+					tasksCommbo.setText(GruntConstants.DEFAULT_COMMAND);
 				} else {
-					tasksCommbo.setText(tasks.iterator().next().getName());
+					tasksCommbo.setText("");
 				}
-			}	
+			}
+
+			String params = lc.getAttribute(GruntConstants.PARAMETERS, (String) null);
+			if (params != null) {
+				parametersText.setText(params);
+			} else {
+				parametersText.setText("");
+			}
 		} catch (CoreException e) {
 			GruntPlugin.logError(e, e.getMessage());
 		}		
@@ -94,6 +128,7 @@
 			wc.setAttribute(GruntConstants.PROJECT, project.getName());
 			wc.setAttribute(GruntConstants.DIR, buildFile.getParent().getLocation().toOSString());
 			wc.setAttribute(GruntConstants.COMMAND, tasksCommbo.getText());
+			wc.setAttribute(GruntConstants.PARAMETERS, parametersText.getText());
 		}
 	}
 	
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/messages.properties b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/messages.properties
index 7e75f10..e0adfe3 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/messages.properties
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/internal/messages.properties
@@ -10,5 +10,6 @@
 ###############################################################################
 GruntLaunchTab_Main=Main
 GruntLaunchTab_ErrorNotExist=Build File does not exist
+GruntLaunchTab_WarningTaskNotExist=Task not found in Gruntfile
 GruntLaunchError_Title=Error Occurred
 GruntLaunchError_Message=Grunt Launch Error
\ No newline at end of file
diff --git a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/util/GruntVisitor.java b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/util/GruntVisitor.java
index dc11fc4..00a58d1 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/util/GruntVisitor.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.grunt/src/org/eclipse/wst/jsdt/js/grunt/util/GruntVisitor.java
@@ -32,6 +32,7 @@
 	private static final String GRUNT_INIT_CONFIG = "grunt.initConfig"; //$NON-NLS-1$
 	private static final String GRUNT_REGISTER_TASK = "grunt.registerTask"; //$NON-NLS-1$
 	private static final String GRUNT_REGISTER_MULTI_TASK = "grunt.registerMultiTask"; //$NON-NLS-1$
+	private static final String GRUNT_PROPERTY_IGNORE = "pkg"; //$NON-NLS-1$
 	
 	private Set<ITask> tasks;
 	private IFile file;
@@ -52,7 +53,8 @@
 			
 			// http://gruntjs.com/api/grunt.task#grunt.task.registertask
 			if (GRUNT_REGISTER_TASK.equals(expression.toString())) {
-				if (argSize == 2) {
+				if (argSize == 2 || argSize == 3) {
+					// Register task supports an optional description field as argument 1.
 					Expression task = arguments.get(0);
 					tasks.add(new GruntTask(ASTUtil.beautify(task), file, false, new Location(task.getStartPosition(), task.getLength()))); 
 				}
@@ -73,6 +75,9 @@
 					List<ObjectLiteralField> fields = jsObject.fields();
 					for (ObjectLiteralField f : fields) {
 						Expression field = f.getFieldName();
+						if (field.toString().equals(GRUNT_PROPERTY_IGNORE)){
+							continue;
+						}
 						tasks.add(new GruntTask((field.toString()), file, false, new Location(field.getStartPosition(), field.getLength())));
 					}
 				}
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/GulpConstants.java b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/GulpConstants.java
index b88dac5..779cb8d 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/GulpConstants.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/GulpConstants.java
@@ -26,8 +26,9 @@
 	public static final String DIR = GulpPlugin.PLUGIN_ID + ".DIR"; //$NON-NLS-1$
 	public static final String COMMAND = GulpPlugin.PLUGIN_ID + ".COMMAND"; //$NON-NLS-1$
 	public static final String BUILD_FILE = GulpPlugin.PLUGIN_ID + ".BUILD_FILE"; //$NON-NLS-1$
+	public static final String PARAMETERS = GulpPlugin.PLUGIN_ID + ".PARAMETERS"; //$NON-NLS-1$
 	
 	public static final String GULP = "gulp"; //$NON-NLS-1$
 	public static final String GULP_FILE_JS = "gilpfile.js"; //$NON-NLS-1$
-
+	public static final String DEFAULT_COMMAND = "default"; //$NON-NLS-1$
 }
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/Messages.java b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/Messages.java
index 4d83b6e..0f349d7 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/Messages.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/Messages.java
@@ -22,6 +22,7 @@
 	public static String GulpLaunchError_Message;
 	public static String GulpLaunchTab_Main;
 	public static String GulpLaunchTab_ErrorNotExist;
+	public static String GulpLaunchTab_WarningTaskNotExist;
 	
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/GulpLaunchConfigurationDelegate.java b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/GulpLaunchConfigurationDelegate.java
index b591c29..85a588d 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/GulpLaunchConfigurationDelegate.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/GulpLaunchConfigurationDelegate.java
@@ -34,11 +34,12 @@
 		String projectName = conf.getAttribute(GulpConstants.PROJECT, (String) null);
 		String dirPath = conf.getAttribute(GulpConstants.DIR, (String) null);
 		String commandName = conf.getAttribute(GulpConstants.COMMAND, (String) null);
+		String parameters = conf.getAttribute(GulpConstants.PARAMETERS, (String) null);
 		
 		IProject project = WorkbenchResourceUtil.getProject(projectName);
 		if (project != null && project.exists()) {
 			IPath dir = (dirPath == null) ? project.getLocation() : new Path(dirPath);
-			CLICommand command = generateCLICommand(commandName);
+			CLICommand command = generateCLICommand(commandName, parameters);
 			launchGulp(project, dir, command, monitor);
 		}	
 	}
@@ -52,8 +53,8 @@
 		}
 	}
 	
-	protected CLICommand generateCLICommand(String commandName) {
-		return new CLICommand(GulpConstants.GULP, commandName, null, null);
+	protected CLICommand generateCLICommand(String commandName, String parameters) {
+		return new CLICommand(GulpConstants.GULP, commandName, parameters, null);
 	}
 
 }
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/shortcut/GulpLaunch.java b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/shortcut/GulpLaunch.java
index a29f32a..1a47739 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/shortcut/GulpLaunch.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/shortcut/GulpLaunch.java
@@ -55,26 +55,28 @@
 	protected void launch(ITask task, String mode) {
 		try {
 			IFile buildFile = task.getBuildFile();
-			ILaunchConfigurationType gulpLaunchConfiguraionType = DebugPlugin.getDefault().getLaunchManager()
+			ILaunchConfigurationType gulpLaunchConfigurationType = DebugPlugin.getDefault().getLaunchManager()
 					.getLaunchConfigurationType(GulpConstants.LAUNCH_CONFIGURATION_ID); 
 			
 			// Check if configuration already exists
 			ILaunchConfiguration[] configurations = DebugPlugin.getDefault()
-					.getLaunchManager().getLaunchConfigurations(gulpLaunchConfiguraionType);
+					.getLaunchManager().getLaunchConfigurations(gulpLaunchConfigurationType);
 			
-			ILaunchConfiguration existingConfiguraion = LaunchConfigurationAutoFill
-					.chooseLaunchConfiguration(configurations, task, GulpConstants.BUILD_FILE);
-			
-			if (existingConfiguraion != null) {
-				ILaunchConfigurationWorkingCopy wc = existingConfiguraion.getWorkingCopy();
-				// Updating task in the existing launch
-				wc.setAttribute(GulpConstants.COMMAND, task.getName());
-				existingConfiguraion = wc.doSave();
-				DebugUITools.launch(existingConfiguraion, mode);
-			// Creating Launch Configuration from scratch
-			} else if (buildFile != null){
+			ILaunchConfiguration[] existingConfigurations = LaunchConfigurationAutoFill
+					.getAllLaunchConfigurations(configurations, task, GulpConstants.BUILD_FILE);
+
+			for (ILaunchConfiguration conf : existingConfigurations) {
+				if (conf.getAttribute(GulpConstants.COMMAND, (String) null).equals(task.getName())) {
+					DebugUITools.launch(conf, mode);
+					return;
+				}
+			}
+
+			// Existing configuration not found, create new Launch Configuration from scratch
+			if (buildFile != null){
 				IProject project = buildFile.getProject();	
-				ILaunchConfigurationWorkingCopy newConfiguration = createEmptyLaunchConfiguration(project.getName() + " [" + buildFile.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				ILaunchConfigurationWorkingCopy newConfiguration = createEmptyLaunchConfiguration(
+						project.getName() + " - " + task.getName() + " [" + buildFile.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 				newConfiguration.setAttribute(GulpConstants.BUILD_FILE, buildFile.getLocation().toOSString());
 				newConfiguration.setAttribute(GulpConstants.PROJECT, project.getName());
 				newConfiguration.setAttribute(GulpConstants.DIR, buildFile.getParent().getLocation().toOSString());
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/ui/GulpLaunchTab.java b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/ui/GulpLaunchTab.java
index 2dc85d9..5b4f857 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/ui/GulpLaunchTab.java
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/launch/ui/GulpLaunchTab.java
@@ -11,6 +11,8 @@
 package org.eclipse.wst.jsdt.js.gulp.internal.launch.ui;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
@@ -38,6 +40,7 @@
 	@Override
 	public boolean isValid(ILaunchConfiguration launchConfig) {
 		setErrorMessage(null);
+		setWarningMessage(null);
 		
 		String buildFilePath = buildFileText.getText();
 		File file = WorkbenchResourceUtil.getFile(buildFilePath);
@@ -46,6 +49,23 @@
 			return false;
 		}
 		
+		// Check if the entered task exists in the Gulpfile, display warning if it does not.
+		try {
+			String task = tasksCommbo.getText();
+			if (task.isEmpty()) {
+				return true;
+			}
+			IFile ifile = WorkbenchResourceUtil.getFileForLocation(file.getAbsolutePath());
+			List<String> availTasks = Arrays.asList(getTaskNames(
+					ASTUtil.getTasks(buildFilePath, new GulpVisitor(ifile))));
+
+			if (!availTasks.contains(task)) {
+				setWarningMessage(Messages.GulpLaunchTab_WarningTaskNotExist);
+			}
+		} catch (JavaScriptModelException e) {
+			GulpPlugin.logError(e, e.getMessage());
+		}
+
 		return true;
 	}
 		
@@ -62,26 +82,33 @@
 		try {
 			buildFileLocation = lc.getAttribute(GulpConstants.BUILD_FILE, (String) null);
 			buildFileText.setText(buildFileLocation != null ? buildFileLocation : ""); //$NON-NLS-1$
-			
-			
+
 			File file = WorkbenchResourceUtil.getFile(buildFileLocation);
 			IFile ifile = null;
 			if (file != null) {
 				ifile = WorkbenchResourceUtil.getFileForLocation(file.getAbsolutePath());
 			}
-			
-			
+
 			Set<ITask> tasks = ASTUtil.getTasks(buildFileLocation, new GulpVisitor(ifile));
-			
-			if (!tasks.isEmpty()) {
-				updateTasks(getTaskNames(tasks));
-				String task = lc.getAttribute(GulpConstants.COMMAND, (String) null);
-				if (task != null && tasks.contains(task)) {
-					tasksCommbo.setText(task);
+			List<String> tasknames = Arrays.asList(getTaskNames(tasks));
+			updateTasks(getTaskNames(tasks));
+			String task = lc.getAttribute(GulpConstants.COMMAND, (String) null);
+			if (task != null && !task.isEmpty()) {
+				tasksCommbo.setText(task);
+			} else {
+				if (tasknames.contains(GulpConstants.DEFAULT_COMMAND)) {
+					tasksCommbo.setText(GulpConstants.DEFAULT_COMMAND);
 				} else {
-					tasksCommbo.setText(tasks.iterator().next().getName());
+					tasksCommbo.setText("");
 				}
-			}	
+			}
+
+			String params = lc.getAttribute(GulpConstants.PARAMETERS, (String) null);
+			if (params != null) {
+				parametersText.setText(params);
+			} else {
+				parametersText.setText("");
+			}
 		} catch (CoreException e) {
 			GulpPlugin.logError(e, e.getMessage());
 		}		
@@ -96,6 +123,7 @@
 			wc.setAttribute(GulpConstants.PROJECT, project.getName());
 			wc.setAttribute(GulpConstants.DIR, buildFile.getParent().getLocation().toOSString());
 			wc.setAttribute(GulpConstants.COMMAND, tasksCommbo.getText());
+			wc.setAttribute(GulpConstants.PARAMETERS, parametersText.getText());
 		}
 	}
 	
diff --git a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/messages.properties b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/messages.properties
index 14bcb20..ef7fb93 100644
--- a/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/messages.properties
+++ b/nodejs/org.eclipse.wst.jsdt.js.gulp/src/org/eclipse/wst/jsdt/js/gulp/internal/messages.properties
@@ -10,5 +10,6 @@
 ###############################################################################
 GulpLaunchTab_Main=Main
 GulpLaunchTab_ErrorNotExist=Build File does not exist
+GulpLaunchTab_WarningTaskNotExist=Task not found in Gulpfile
 GulpLaunchError_Title=Error Occurred
 GulpLaunchError_Message=Gulp Launch Error
\ No newline at end of file
diff --git a/tests/org.eclipse.wst.jsdt.js.common.tests/src/org/eclipse/wst/jsdt/js/common/tests/BuildSystemVisitorTest.java b/tests/org.eclipse.wst.jsdt.js.common.tests/src/org/eclipse/wst/jsdt/js/common/tests/BuildSystemVisitorTest.java
index 4152eea..47528d6 100644
--- a/tests/org.eclipse.wst.jsdt.js.common.tests/src/org/eclipse/wst/jsdt/js/common/tests/BuildSystemVisitorTest.java
+++ b/tests/org.eclipse.wst.jsdt.js.common.tests/src/org/eclipse/wst/jsdt/js/common/tests/BuildSystemVisitorTest.java
@@ -32,6 +32,7 @@
 import org.eclipse.wst.jsdt.js.common.tests.util.ResourceUtil;
 import org.eclipse.wst.jsdt.js.grunt.util.GruntVisitor;
 import org.eclipse.wst.jsdt.js.gulp.util.GulpVisitor;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -61,6 +62,12 @@
 		gulpfile.create(new FileInputStream(gulp.getAbsolutePath()), true, null);
 	}
 
+	@AfterClass
+	public static void teardown() throws CoreException {
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestJsProject");
+		project.delete(true, true, null);
+	}
+
 	@Test
 	public void GruntTasksTest() {
 		try {
@@ -69,8 +76,8 @@
 			unit.accept(visitor);
 			Set<ITask> tasks = visitor.getTasks();
 			assertTrue("Task list is empty", !tasks.isEmpty());
-			// There are 8 tasks defined in gruntfile.js
-			assertTrue("Not all grunt tasks were found", tasks.size() == 8);
+			// There are 7 tasks defined in gruntfile.js
+			assertTrue("Not all grunt tasks were found", tasks.size() == 7);
 		} catch (CoreException e) {
 			fail("Exception occured while reading file");
 		}