Skip to content

Commit

Permalink
finx: Run/Debug with contextual menu
Browse files Browse the repository at this point in the history
Fixes redhat-developer#760

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jan 23, 2025
1 parent 9bb7c8d commit 92d2c48
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.redhat.devtools.lsp4ij.dap.DebuggingType;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptor;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactory;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactoryRegistry;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
import com.redhat.devtools.lsp4ij.launching.ServerMappingSettings;
import com.redhat.devtools.lsp4ij.settings.ServerTrace;
Expand Down Expand Up @@ -234,12 +233,28 @@ public void checkConfiguration() throws RuntimeConfigurationException {
}

@Nullable
private DebugAdapterDescriptorFactory getServerFactory() {
String serverId = getOptions().getServerId();
if (StringUtils.isBlank(serverId)) {
return null;
}
return DebugAdapterDescriptorFactoryRegistry.getInstance().getFactoryById(serverId);
public DebugAdapterDescriptorFactory getServerFactory() {
return getOptions().getServerFactory();
}

public void copyConfigurationTo(DAPRunConfiguration configuration) {
// Configuration
configuration.setWorkingDirectory(getWorkingDirectory());
configuration.setFile(getFile());
configuration.setDebuggingType(getDebuggingType());
configuration.setLaunchParameters(getLaunchParameters());
configuration.setAttachParameters(getAttachParameters());

// Mappings
configuration.setServerMappings(getServerMappings());

// Server
configuration.setServerId(getServerId());
configuration.setServerName(getServerName());
configuration.setCommand(getCommand());
configuration.setConnectingServerStrategy(getConnectingServerStrategy());
configuration.setWaitForTimeout(getWaitForTimeout());
configuration.setWaitForTrace(getWaitForTrace());
configuration.setServerTrace(getServerTrace());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import com.redhat.devtools.lsp4ij.dap.ConnectingServerStrategy;
import com.redhat.devtools.lsp4ij.dap.DebuggingType;
import com.redhat.devtools.lsp4ij.dap.configurations.extractors.NetworkAddressExtractor;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactory;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactoryRegistry;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
import com.redhat.devtools.lsp4ij.launching.ServerMappingSettings;
import com.redhat.devtools.lsp4ij.settings.ServerTrace;
Expand Down Expand Up @@ -47,7 +49,7 @@ public class DAPRunConfigurationOptions extends RunConfigurationOptions {
.provideDelegate(this, "attachParameters");

// Mappings settings
private final StoredProperty<List<ServerMappingSettings>> serverMappings = this.<ServerMappingSettings >list()
private final StoredProperty<List<ServerMappingSettings>> serverMappings = this.<ServerMappingSettings>list()
.provideDelegate(this, "serverMappings");

// Server settings
Expand All @@ -59,10 +61,10 @@ public class DAPRunConfigurationOptions extends RunConfigurationOptions {

private final StoredProperty<String> command = string("")
.provideDelegate(this, "command");

private final StoredProperty<String> connectingServerStrategy = string(ConnectingServerStrategy.NONE.name())
.provideDelegate(this, "connectingServerStrategy");

private final StoredProperty<Integer> waitForTimeout = property(0)
.provideDelegate(this, "waitForTimeout");

Expand Down Expand Up @@ -195,7 +197,7 @@ public void setWaitForTrace(String waitForTrace) {
this.waitForTrace.setValue(this, waitForTrace);
this.networkAddressExtractor = null;
}

public int getWaitForTimeout() {
return waitForTimeout.getValue(this);
}
Expand All @@ -222,4 +224,12 @@ public void setServerTrace(ServerTrace serverTrace) {
}
return networkAddressExtractor;
}

public @Nullable DebugAdapterDescriptorFactory getServerFactory() {
String serverId = getServerId();
if (StringUtils.isBlank(serverId)) {
return null;
}
return DebugAdapterDescriptorFactoryRegistry.getInstance().getFactoryById(serverId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2025 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.lsp4ij.dap.configurations;

import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactoryRegistry;
import org.jetbrains.annotations.NotNull;

/**
* Default Debug Adapter Protocol (DAP) run configuration provider.
*/
public class DAPRunConfigurationProvider extends LazyRunConfigurationProducer<DAPRunConfiguration> {

@Override
public @NotNull ConfigurationFactory getConfigurationFactory() {
return DAPRunConfigurationType.getInstance().getConfigurationFactories()[0];
}

@Override
protected boolean setupConfigurationFromContext(@NotNull DAPRunConfiguration configuration,
@NotNull ConfigurationContext context,
@NotNull Ref<PsiElement> sourceElement) {
var location = context.getLocation();
if (location == null) {
return false;
}
var file = location.getVirtualFile();
if (file == null) {
return false;
}
var project= location.getProject();
if (project.isDisposed()) {
return false;
}
return DebugAdapterDescriptorFactoryRegistry.getInstance().prepareConfiguration(configuration, file, project);
}

@Override
public boolean isConfigurationFromContext(@NotNull DAPRunConfiguration configuration,
@NotNull ConfigurationContext context) {
var location = context.getLocation();
if (location == null) {
return false;
}
var file = location.getVirtualFile();
if (file == null) {
return false;
}
return configuration.canDebug(file);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package com.redhat.devtools.lsp4ij.dap.configurations;

import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.util.NotNullLazyValue;
import com.redhat.devtools.lsp4ij.dap.DAPBundle;
Expand All @@ -22,6 +23,10 @@ final class DAPRunConfigurationType extends ConfigurationTypeBase {

public static final String ID = "DAPRunConfiguration";

public static DAPRunConfigurationType getInstance() {
return ConfigurationTypeUtil.findConfigurationType(DAPRunConfigurationType.class);
}

DAPRunConfigurationType() {
super(ID,
DAPBundle.message("DAPRunConfigurationType.displayName"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
******************************************************************************/
package com.redhat.devtools.lsp4ij.dap.configurations;

import com.google.common.collect.Streams;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
Expand Down Expand Up @@ -315,7 +314,7 @@ protected void applyEditorTo(@NotNull DAPRunConfiguration runConfiguration) {

if (currentServerFactory != null) {
runConfiguration.setServerId(currentServerFactory.getId());
currentServerFactory.setServerTrace((ServerTrace) serverTraceComboBox.getSelectedItem());
/*currentServerFactory.setServerTrace((ServerTrace) serverTraceComboBox.getSelectedItem());
if (currentServerFactory instanceof UserDefinedDebugAdapterDescriptorFactory dapFactory) {
runConfiguration.setServerId(dapFactory.getId());
if (dapFactory != UserDefinedDebugAdapterDescriptorFactory.NONE) {
Expand All @@ -329,7 +328,7 @@ protected void applyEditorTo(@NotNull DAPRunConfiguration runConfiguration) {
mappingsPanel.getFileNamePatternMappings().stream()
).toList());
}
}
}*/
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.redhat.devtools.lsp4ij.dap.client.DAPClient;
import com.redhat.devtools.lsp4ij.dap.client.LaunchUtils;
import com.redhat.devtools.lsp4ij.dap.configurations.DAPRunConfigurationOptions;
import com.redhat.devtools.lsp4ij.dap.descriptors.userdefined.UserDefinedDebugAdapterDescriptorFactory;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
import com.redhat.devtools.lsp4ij.server.definition.launching.CommandUtils;
import com.redhat.devtools.lsp4ij.settings.ServerTrace;
Expand Down Expand Up @@ -100,18 +101,21 @@ public ProcessHandler startServer() throws ExecutionException {
@Nullable
protected GeneralCommandLine createStartCommandLine(@NotNull RunConfigurationOptions options) throws ExecutionException {
if (options instanceof DAPRunConfigurationOptions dapOptions) {
// Download tar gz at https://github.com/microsoft/vscode-js-debug/releases/
// GeneralCommandLine commandLine = new GeneralCommandLine("node",
// "C:/Users/azerr/Downloads/js-debug-dap-v1.83.0/js-debug/src/dapDebugServer.js",
// String.valueOf(port));
return generateStartDAPClientCommand(dapOptions.getCommand());
String command = dapOptions.getCommand();
if (StringUtils.isBlank(command)) {
var factory = dapOptions.getServerFactory();
if (factory instanceof UserDefinedDebugAdapterDescriptorFactory userDefinedFactory) {
command = userDefinedFactory.getCommandLine();
}
}
return generateStartDAPClientCommand(command);
}
return null;
}

protected @NotNull GeneralCommandLine generateStartDAPClientCommand(@Nullable String command) throws ExecutionException {
if (StringUtils.isBlank(command)) {
throw new ExecutionException("DAP command must be specified.");
throw new ExecutionException("DAP server command must be specified.");
}
Integer port = null;
int portIndex = command.indexOf($_PORT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.redhat.devtools.lsp4ij.dap.DebuggingType;
import com.redhat.devtools.lsp4ij.dap.configurations.DAPRunConfiguration;
import com.redhat.devtools.lsp4ij.dap.configurations.DAPRunConfigurationOptions;
import com.redhat.devtools.lsp4ij.dap.configurations.DAPSettingsEditor;
import com.redhat.devtools.lsp4ij.dap.descriptors.userdefined.UserDefinedDebugAdapterDescriptorFactory;
Expand Down Expand Up @@ -81,4 +83,20 @@ public abstract boolean canDebug(@NotNull VirtualFile file,
public boolean canRun(@NotNull String executorId) {
return true;
}

public boolean prepareConfiguration(@NotNull RunConfiguration configuration,
@NotNull VirtualFile file,
@NotNull Project project) {
if (configuration instanceof DAPRunConfiguration dapConfiguration) {
// Configuration
dapConfiguration.setFile(file.toNioPath().toString());
dapConfiguration.setDebuggingType(DebuggingType.LAUNCH);

// Server
dapConfiguration.setServerId(this.getId());
dapConfiguration.setServerName(this.getName());
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import com.redhat.devtools.lsp4ij.internal.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

Expand All @@ -31,8 +29,6 @@
*/
public class DebugAdapterDescriptorFactoryRegistry {

private static final Logger LOGGER = LoggerFactory.getLogger(DebugAdapterDescriptorFactoryRegistry.class);

public static DebugAdapterDescriptorFactoryRegistry getInstance() {
return ApplicationManager.getApplication().getService(DebugAdapterDescriptorFactoryRegistry.class);
}
Expand Down Expand Up @@ -65,21 +61,53 @@ public Collection<DebugAdapterDescriptorFactory> getFactories() {
public boolean canDebug(@NotNull VirtualFile file,
@NotNull Project project) {
// Search canDebug inside the factories
for(var factory : factories.values()) {
if(factory.canDebug(file, project)) {
return true;
}
if (findFactoryFor(file, project) != null) {
return true;
}

// Search canDebug in existing DAP run configuration
return findExistingConfigurationFor(file, project) != null;
}

private static RunConfiguration findExistingConfigurationFor(@NotNull VirtualFile file, @NotNull Project project) {
List<RunConfiguration> all = RunManager.getInstance(project).getAllConfigurationsList();
for (var runConfiguration : all) {
if (runConfiguration instanceof DAPRunConfiguration dapConfig) {
if (StringUtils.isEmpty(dapConfig.getServerId()) && dapConfig.canDebug(file)) {
return true;
return runConfiguration;
}
}
}
return null;
}

@Nullable
private DebugAdapterDescriptorFactory findFactoryFor(@NotNull VirtualFile file,
@NotNull Project project) {
for(var factory : factories.values()) {
if(factory.canDebug(file, project)) {
return factory;
}
}
return null;
}

public boolean prepareConfiguration(@NotNull RunConfiguration configuration,
@NotNull VirtualFile file,
@NotNull Project project) {
RunConfiguration existingConfiguration = findExistingConfigurationFor(file, project);
if(existingConfiguration != null
&& existingConfiguration instanceof DAPRunConfiguration existingDapConfiguration
&& configuration instanceof DAPRunConfiguration dapConfiguration) {
existingDapConfiguration.copyConfigurationTo(dapConfiguration);
// Override file to debug
existingDapConfiguration.setFile(file.toNioPath().toString());
return true;
}
DebugAdapterDescriptorFactory factory = findFactoryFor(file, project);
if (factory != null) {
return factory.prepareConfiguration(configuration, file, project);
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@
******************************************************************************/
package com.redhat.devtools.lsp4ij.dap.descriptors.templates;

import com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactory;
import com.redhat.devtools.lsp4ij.dap.descriptors.userdefined.UserDefinedDebugAdapterDescriptorFactory;
import org.jetbrains.annotations.NotNull;

/**
* Template {@link DebugAdapterDescriptorFactory}.
* Template {@link com.redhat.devtools.lsp4ij.dap.descriptors.DebugAdapterDescriptorFactory}.
*/
public class TemplateDebugAdapterDescriptorFactory extends UserDefinedDebugAdapterDescriptorFactory {

Expand Down
Loading

0 comments on commit 92d2c48

Please sign in to comment.