Skip to content

Commit 8319eec

Browse files
authored
Merge pull request #36 from eharris369/35-addNodeJSDebugSupport
Issue #35: Add support for debugging Node.js projects
2 parents 99cfb70 + d9c6f07 commit 8319eec

File tree

16 files changed

+941
-67
lines changed

16 files changed

+941
-67
lines changed

dev/com.ibm.microclimate.core/src/com/ibm/microclimate/core/MicroclimateCorePlugin.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018 IBM Corporation and others.
2+
* Copyright (c) 2018, 2019 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -12,12 +12,15 @@
1212
package com.ibm.microclimate.core;
1313

1414
import java.net.URL;
15+
import java.util.HashMap;
16+
import java.util.Map;
1517

1618
import org.eclipse.jface.resource.ImageDescriptor;
1719
import org.eclipse.osgi.service.debug.DebugOptionsListener;
1820
import org.eclipse.ui.plugin.AbstractUIPlugin;
1921
import org.osgi.framework.BundleContext;
2022

23+
import com.ibm.microclimate.core.internal.IDebugLauncher;
2124
import com.ibm.microclimate.core.internal.IUpdateHandler;
2225
import com.ibm.microclimate.core.internal.MCEclipseApplication;
2326
import com.ibm.microclimate.core.internal.MCLogger;
@@ -35,11 +38,15 @@ public class MicroclimateCorePlugin extends AbstractUIPlugin {
3538
public static final String
3639
// Int option for debug timeout in seconds
3740
DEBUG_CONNECT_TIMEOUT_PREFSKEY = "serverDebugTimeout"; //$NON-NLS-1$
41+
42+
public static final String NODEJS_DEBUG_BROWSER_PREFSKEY = "nodejsDebugBrowserName"; //$NON-NLS-1$
3843

3944
// The shared instance
4045
private static MicroclimateCorePlugin plugin;
4146

4247
private static IUpdateHandler updateHandler;
48+
49+
private static Map<String, IDebugLauncher> debugLaunchers = new HashMap<String, IDebugLauncher>();
4350

4451
/**
4552
* The constructor
@@ -95,5 +102,13 @@ public static void setUpdateHandler(IUpdateHandler handler) {
95102
public static IUpdateHandler getUpdateHandler() {
96103
return updateHandler;
97104
}
105+
106+
public static void addDebugLauncher(String language, IDebugLauncher launcher) {
107+
debugLaunchers.put(language, launcher);
108+
}
109+
110+
public static IDebugLauncher getDebugLauncher(String language) {
111+
return debugLaunchers.get(language);
112+
}
98113

99114
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019 IBM Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* IBM Corporation - initial API and implementation
10+
*******************************************************************************/
11+
12+
package com.ibm.microclimate.core.internal;
13+
14+
import org.eclipse.core.runtime.IStatus;
15+
16+
public interface IDebugLauncher {
17+
18+
public IStatus launchDebugger(MicroclimateApplication app);
19+
20+
public boolean canAttachDebugger(MicroclimateApplication app);
21+
22+
}

dev/com.ibm.microclimate.core/src/com/ibm/microclimate/core/internal/MCEclipseApplication.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,23 +138,31 @@ public void clearDebugger() {
138138
@Override
139139
public void connectDebugger() {
140140
final MCEclipseApplication app = this;
141-
Job job = new Job(Messages.ReconnectDebugJob) {
141+
Job job = new Job(Messages.ConnectDebugJob) {
142142
@Override
143143
protected IStatus run(IProgressMonitor monitor) {
144144
try {
145-
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
146-
ILaunchConfigurationType launchConfigurationType = launchManager.getLaunchConfigurationType(MicroclimateLaunchConfigDelegate.LAUNCH_CONFIG_ID);
147-
ILaunchConfigurationWorkingCopy workingCopy = launchConfigurationType.newInstance((IContainer) null, app.name);
148-
MicroclimateLaunchConfigDelegate.setConfigAttributes(workingCopy, app);
149-
ILaunchConfiguration launchConfig = workingCopy.doSave();
150-
ILaunch launch = launchConfig.launch(ILaunchManager.DEBUG_MODE, monitor);
151-
app.setLaunch(launch);
152-
return Status.OK_STATUS;
145+
if (app.projectType.isLanguage(ProjectType.LANGUAGE_JAVA)) {
146+
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
147+
ILaunchConfigurationType launchConfigurationType = launchManager.getLaunchConfigurationType(MicroclimateLaunchConfigDelegate.LAUNCH_CONFIG_ID);
148+
ILaunchConfigurationWorkingCopy workingCopy = launchConfigurationType.newInstance((IContainer) null, app.name);
149+
MicroclimateLaunchConfigDelegate.setConfigAttributes(workingCopy, app);
150+
ILaunchConfiguration launchConfig = workingCopy.doSave();
151+
ILaunch launch = launchConfig.launch(ILaunchManager.DEBUG_MODE, monitor);
152+
app.setLaunch(launch);
153+
return Status.OK_STATUS;
154+
} else {
155+
IDebugLauncher launcher = MicroclimateCorePlugin.getDebugLauncher(app.projectType.language);
156+
if (launcher != null) {
157+
return launcher.launchDebugger(app);
158+
}
159+
}
153160
} catch (Exception e) {
154161
MCLogger.logError("An error occurred while trying to launch the debugger for project: " + app.name); //$NON-NLS-1$
155162
return new Status(IStatus.ERROR, MicroclimateCorePlugin.PLUGIN_ID,
156163
NLS.bind(Messages.DebugLaunchError, app.name), e);
157164
}
165+
return Status.CANCEL_STATUS;
158166
}
159167
};
160168
job.setPriority(Job.LONG);
@@ -181,6 +189,20 @@ public void reconnectDebugger() {
181189
}
182190
}
183191

192+
public boolean canAttachDebugger() {
193+
if (projectType.isLanguage(ProjectType.LANGUAGE_JAVA)) {
194+
IDebugTarget debugTarget = getDebugTarget();
195+
return (debugTarget == null || debugTarget.isDisconnected());
196+
} else {
197+
IDebugLauncher launcher = MicroclimateCorePlugin.getDebugLauncher(projectType.language);
198+
if (launcher != null) {
199+
return launcher.canAttachDebugger(this);
200+
}
201+
}
202+
return false;
203+
204+
}
205+
184206
public void attachDebugger() {
185207
// Remove any existing launch such as for a disconnected debug target
186208
if (launch != null) {
@@ -283,10 +305,10 @@ private void validationEvent(int severity, String filePath, String message, Stri
283305
@Override
284306
public boolean supportsDebug() {
285307
// Only supported for certain project types
286-
if (projectType.isType(ProjectType.TYPE_LIBERTY) || projectType.isType(ProjectType.TYPE_SPRING)) {
308+
if (projectType.isType(ProjectType.TYPE_LIBERTY) || projectType.isType(ProjectType.TYPE_SPRING) || projectType.isType(ProjectType.TYPE_NODEJS)) {
287309
// And only if the project supports it
288310
ProjectCapabilities capabilities = getProjectCapabilities();
289-
return capabilities.supportsDebugMode() && capabilities.canRestart();
311+
return (capabilities.supportsDebugMode() || capabilities.supportsDebugNoInitMode()) && capabilities.canRestart();
290312
}
291313
return false;
292314
}

dev/com.ibm.microclimate.core/src/com/ibm/microclimate/core/internal/constants/ProjectCapabilities.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018 IBM Corporation and others.
2+
* Copyright (c) 2018, 2019 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -32,7 +32,8 @@ public class ProjectCapabilities {
3232

3333
public enum StartMode {
3434
RUN("run"),
35-
DEBUG("debug");
35+
DEBUG("debug"),
36+
DEBUG_NO_INIT("debugNoInit");
3637

3738
private final String name;
3839

@@ -118,5 +119,9 @@ public boolean canRestart() {
118119
public boolean supportsDebugMode() {
119120
return startModes.contains(StartMode.DEBUG);
120121
}
122+
123+
public boolean supportsDebugNoInitMode() {
124+
return startModes.contains(StartMode.DEBUG_NO_INIT);
125+
}
121126

122127
}

dev/com.ibm.microclimate.core/src/com/ibm/microclimate/core/internal/messages/Messages.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public class Messages extends NLS {
5858
public static String BuildStateUnknown;
5959

6060
public static String DebugLaunchError;
61-
public static String ReconnectDebugJob;
61+
public static String ConnectDebugJob;
6262

6363
public static String RefreshResourceJobLabel;
6464
public static String RefreshResourceError;

dev/com.ibm.microclimate.core/src/com/ibm/microclimate/core/internal/messages/messages.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ BuildStateFailed=Build failed
5151
BuildStateUnknown=No build status information
5252

5353
DebugLaunchError=An error occurred trying to launch the debugger for the {0} project.
54-
ReconnectDebugJob=Reconnect debugger
54+
ConnectDebugJob=Connect debugger
5555

5656
RefreshResourceJobLabel=Refreshing resource: {0}
5757
RefreshResourceError=An error occurred while trying to refresh the {0} resource.

dev/com.ibm.microclimate.ui/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ Import-Package: org.eclipse.tm.terminal.view.core.interfaces.constants,
2424
org.eclipse.tm.terminal.view.ui.launcher,
2525
org.eclipse.ui.console,
2626
org.eclipse.ui.navigator,
27+
org.eclipse.ui.internal.browser,
2728
org.eclipse.ui.internal.wizards.datatransfer

dev/com.ibm.microclimate.ui/src/com/ibm/microclimate/ui/MicroclimateUIPlugin.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018 IBM Corporation and others.
2+
* Copyright (c) 2018, 2019 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -24,6 +24,8 @@
2424

2525
import com.ibm.microclimate.core.MicroclimateCorePlugin;
2626
import com.ibm.microclimate.core.internal.MCLogger;
27+
import com.ibm.microclimate.core.internal.constants.ProjectType;
28+
import com.ibm.microclimate.ui.internal.debug.NodeJSDebugLauncher;
2729
import com.ibm.microclimate.ui.internal.views.UpdateHandler;
2830

2931
/**
@@ -72,6 +74,7 @@ public void start(BundleContext context) throws Exception {
7274
super.start(context);
7375
plugin = this;
7476
MicroclimateCorePlugin.setUpdateHandler(new UpdateHandler());
77+
MicroclimateCorePlugin.addDebugLauncher(ProjectType.LANGUAGE_NODEJS, new NodeJSDebugLauncher());
7578
}
7679

7780
/*

dev/com.ibm.microclimate.ui/src/com/ibm/microclimate/ui/internal/actions/AttachDebuggerAction.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018 IBM Corporation and others.
2+
* Copyright (c) 2018, 2019 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -11,7 +11,6 @@
1111

1212
package com.ibm.microclimate.ui.internal.actions;
1313

14-
import org.eclipse.debug.core.model.IDebugTarget;
1514
import org.eclipse.jface.viewers.ISelectionProvider;
1615
import org.eclipse.jface.viewers.IStructuredSelection;
1716
import org.eclipse.ui.actions.SelectionProviderAction;
@@ -44,8 +43,7 @@ public void selectionChanged(IStructuredSelection sel) {
4443
app = (MCEclipseApplication) obj;
4544
if (app.isAvailable() && StartMode.DEBUG_MODES.contains(app.getStartMode()) && app.getDebugPort() != -1 &&
4645
(app.getAppState() == AppState.STARTED || app.getAppState() == AppState.STARTING)) {
47-
IDebugTarget debugTarget = app.getDebugTarget();
48-
setEnabled(debugTarget == null || debugTarget.isDisconnected());
46+
setEnabled(app.canAttachDebugger());
4947
return;
5048
}
5149
}

dev/com.ibm.microclimate.ui/src/com/ibm/microclimate/ui/internal/actions/RestartDebugModeAction.java

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018 IBM Corporation and others.
2+
* Copyright (c) 2018, 2019 IBM Corporation and others.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -36,6 +36,7 @@
3636
import com.ibm.microclimate.core.internal.MCLogger;
3737
import com.ibm.microclimate.core.internal.MCUtil;
3838
import com.ibm.microclimate.core.internal.constants.AppState;
39+
import com.ibm.microclimate.core.internal.constants.ProjectType;
3940
import com.ibm.microclimate.core.internal.constants.StartMode;
4041
import com.ibm.microclimate.ui.MicroclimateUIPlugin;
4142
import com.ibm.microclimate.ui.internal.messages.Messages;
@@ -77,40 +78,44 @@ public void run(IAction action) {
7778
return;
7879
}
7980

80-
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(app.name);
81-
// Check if the project has been imported into Eclipse. If not, offer to import it.
82-
if (project == null || !project.exists()) {
83-
int result = openDialog(NLS.bind(Messages.ProjectNotImportedDialogTitle, app.name), NLS.bind(Messages.ProjectNotImportedDialogMsg, app.name));
84-
if (result == 0) {
85-
// Import the project
86-
ImportProjectAction.importProject(app);
87-
} else if (result == 2) {
88-
// Cancel selected
89-
return;
90-
}
91-
// Check if the project is open in Eclipse. If not, offer to open it.
92-
} else if (!project.isOpen()) {
93-
int result = openDialog(NLS.bind(Messages.ProjectClosedDialogTitle, app.name), NLS.bind(Messages.ProjectClosedDialogMsg, app.name));
94-
if (result == 0) {
95-
// Open the project
96-
Job job = new Job(NLS.bind(Messages.ProjectOpenJob, app.name)) {
97-
@Override
98-
protected IStatus run(IProgressMonitor monitor) {
99-
try {
100-
project.open(monitor);
101-
return Status.OK_STATUS;
102-
} catch (CoreException e) {
103-
return new Status(IStatus.ERROR, MicroclimateUIPlugin.PLUGIN_ID,
104-
NLS.bind(Messages.ProjectOpenError, app.name), e);
105-
}
106-
}
107-
};
108-
job.setPriority(Job.LONG);
109-
job.schedule();
110-
} else if (result == 2) {
111-
// Cancel selected
112-
return;
113-
}
81+
// Check for a project for Java applications only since currently this is the only
82+
// language that can be debugged within Eclipse
83+
if (app.projectType.isLanguage(ProjectType.LANGUAGE_JAVA)) {
84+
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(app.name);
85+
// Check if the project has been imported into Eclipse. If not, offer to import it.
86+
if (project == null || !project.exists()) {
87+
int result = openDialog(NLS.bind(Messages.ProjectNotImportedDialogTitle, app.name), NLS.bind(Messages.ProjectNotImportedDialogMsg, app.name));
88+
if (result == 0) {
89+
// Import the project
90+
ImportProjectAction.importProject(app);
91+
} else if (result == 2) {
92+
// Cancel selected
93+
return;
94+
}
95+
// Check if the project is open in Eclipse. If not, offer to open it.
96+
} else if (!project.isOpen()) {
97+
int result = openDialog(NLS.bind(Messages.ProjectClosedDialogTitle, app.name), NLS.bind(Messages.ProjectClosedDialogMsg, app.name));
98+
if (result == 0) {
99+
// Open the project
100+
Job job = new Job(NLS.bind(Messages.ProjectOpenJob, app.name)) {
101+
@Override
102+
protected IStatus run(IProgressMonitor monitor) {
103+
try {
104+
project.open(monitor);
105+
return Status.OK_STATUS;
106+
} catch (CoreException e) {
107+
return new Status(IStatus.ERROR, MicroclimateUIPlugin.PLUGIN_ID,
108+
NLS.bind(Messages.ProjectOpenError, app.name), e);
109+
}
110+
}
111+
};
112+
job.setPriority(Job.LONG);
113+
job.schedule();
114+
} else if (result == 2) {
115+
// Cancel selected
116+
return;
117+
}
118+
}
114119
}
115120

116121
try {
@@ -119,7 +124,16 @@ protected IStatus run(IProgressMonitor monitor) {
119124

120125
// Restart the project in debug mode. The debugger will be attached when the restart result
121126
// event is received from Microclimate.
122-
app.mcConnection.requestProjectRestart(app, StartMode.DEBUG.startMode);
127+
// Try debug mode first since it allows debug of initialization. If not supported use
128+
// debugNoInit mode.
129+
if (app.getProjectCapabilities().supportsDebugMode()) {
130+
app.mcConnection.requestProjectRestart(app, StartMode.DEBUG.startMode);
131+
} else if (app.getProjectCapabilities().supportsDebugNoInitMode()) {
132+
app.mcConnection.requestProjectRestart(app, StartMode.DEBUG_NO_INIT.startMode);
133+
} else {
134+
// Should never get here
135+
MCLogger.logError("Project restart in debug mode requested but project does not support any debug modes: " + app.name); //$NON-NLS-1$
136+
}
123137
} catch (Exception e) {
124138
MCLogger.logError("Error initiating restart for project: " + app.name, e); //$NON-NLS-1$
125139
MCUtil.openDialog(true, Messages.ErrorOnRestartDialogTitle, e.getMessage());

0 commit comments

Comments
 (0)