Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support executing debug in the browser #10748

Merged
merged 1 commit into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [plugin] Support `TextEditor#show()` and `TextEditor#hide()` [#11168](https://github.com/eclipse-theia/theia/pull/11168) - Contributed on behalf of STMicroelectronics
- [core, monaco] refactored theme initialization to occur within application lifecycle rather than at import time. [#11213](https://github.com/eclipse-theia/theia/pull/11213)
- [plugin] Support optional property `TaskPresentationOptions#clear` [#11298](https://github.com/eclipse-theia/theia/pull/11298) - Contributed on behalf of STMicroelectronics
- [plugin] added support for debuggers running in the frontend [#10748](https://github.com/eclipse-theia/theia/pull/10748)

<a name="breaking_changes_1.27.0">[Breaking Changes:](#breaking_changes_1.27.0)</a>

Expand Down Expand Up @@ -60,6 +61,9 @@
- [core] removed `ThemeService.get()`; inject the `ThemeService` instead. Removed `ColorApplicationContribution.initBackground()`; by default the `editor.background` color variable will be initialized through the normal theme initialization process. It is now expected that the `ThemeService` will call `this.deferredInitializer.resolve()` when the `ThemeService` finishes its initialization. Failure to do so in any overrides may cause failures to apply default themes. [#11213](https://github.com/eclipse-theia/theia/pull/11213)
- [monaco] removed static methods `init()`, `register()`, `restore(), `updateBodyUiTheme()` from `MonacoThemingService`; use instance methods `initialize()`, `registerParsedTheme()`, `restore()`, `updateBodyUiTheme()` instead. Removed `MonacoThemeRegistry.SINGLETON`, inject `MonacoThemeRegistry` instead. [#11213](https://github.com/eclipse-theia/theia/pull/11213)
- [core] double-click no longer maximizes a tab by default - controllable through `workbench.tab.maximize` preference [#11279](https://github.com/eclipse-theia/theia/pull/11279)
- [plugin-ext] method `registerDebuggersContributions` has an additional parameter in the signature `pluginType` to specify `frontend` or `backend` [#10748](https://github.com/eclipse-theia/theia/pull/10748)
- [plugin-ext] file `debug` renamed to `debug-ext` [#10748](https://github.com/eclipse-theia/theia/pull/10748)
- [debug] debug files not unique to the backend have been moved from `node` to `common` [#10748](https://github.com/eclipse-theia/theia/pull/10748)

## v1.26.0 - 5/26/2022

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

import { injectable, inject, named } from '@theia/core/shared/inversify';
import { ContributionProvider } from '@theia/core';
import { DebugConfiguration } from '../common/debug-configuration';
import { DebuggerDescription, DebugError } from '../common/debug-service';
import { DebugConfiguration } from './debug-configuration';
import { DebuggerDescription, DebugError } from './debug-service';

import { DebugAdapterContribution, DebugAdapterExecutable, DebugAdapterSessionFactory } from './debug-model';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
DebugAdapterSession
} from './debug-model';
import { DebugProtocol } from 'vscode-debugprotocol';
import { DebugChannel } from '../common/debug-service';
import { DebugChannel } from './debug-service';

/**
* [DebugAdapterSession](#DebugAdapterSession) implementation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
// Some entities copied and modified from https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts
// Some entities copied and modified from https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/debug/common/debug.ts

import { DebugConfiguration } from '../common/debug-configuration';
import { DebugConfiguration } from './debug-configuration';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { MaybePromise } from '@theia/core/lib/common/types';
import { Event } from '@theia/core';
import { DebugChannel } from '../common/debug-service';
import { DebugChannel } from './debug-service';

// FIXME: break down this file to debug adapter and debug adapter contribution (see Theia file naming conventions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// *****************************************************************************

import { Emitter, Event } from '@theia/core/lib/common/event';
import { DebugAdapter } from '@theia/debug/lib/node/debug-model';
import { DebugAdapter } from './debug-model';
import * as theia from '@theia/plugin';

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/debug/src/node/debug-adapter-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ import {
DebugAdapterFactory,
DebugAdapterForkExecutable,
DebugAdapter
} from './debug-model';
import { DebugAdapterSessionImpl } from './debug-adapter-session';
} from '../common/debug-model';
import { DebugAdapterSessionImpl } from '../common/debug-adapter-session';
import { environment } from '@theia/core/shared/@theia/application-package';
import { ProcessDebugAdapter, SocketDebugAdapter } from './stream-debug-adapter';

Expand Down
4 changes: 2 additions & 2 deletions packages/debug/src/node/debug-adapter-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { MessagingService } from '@theia/core/lib/node/messaging/messaging-servi

import { DebugAdapterPath, ForwardingDebugChannel } from '../common/debug-service';
import { DebugConfiguration } from '../common/debug-configuration';
import { DebugAdapterSession, DebugAdapterSessionFactory, DebugAdapterFactory } from './debug-model';
import { DebugAdapterContributionRegistry } from './debug-adapter-contribution-registry';
import { DebugAdapterSession, DebugAdapterSessionFactory, DebugAdapterFactory } from '../common/debug-model';
import { DebugAdapterContributionRegistry } from '../common/debug-adapter-contribution-registry';

/**
* Debug adapter session manager.
Expand Down
4 changes: 2 additions & 2 deletions packages/debug/src/node/debug-backend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import {
DebugAdapterContribution,
DebugAdapterSessionFactory,
DebugAdapterFactory
} from './debug-model';
} from '../common/debug-model';
import { DebugServiceImpl } from './debug-service-impl';
import { DebugAdapterContributionRegistry } from './debug-adapter-contribution-registry';
import { DebugAdapterContributionRegistry } from '../common/debug-adapter-contribution-registry';
import { DebugAdapterSessionManager } from './debug-adapter-session-manager';

const debugConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/debug/src/node/debug-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { DebugService, DebuggerDescription } from '../common/debug-service';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { CommandIdVariables } from '@theia/variable-resolver/lib/common/variable-types';
import { DebugAdapterSessionManager } from './debug-adapter-session-manager';
import { DebugAdapterContributionRegistry } from './debug-adapter-contribution-registry';
import { DebugAdapterContributionRegistry } from '../common/debug-adapter-contribution-registry';
import { Event } from '@theia/core';

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/debug/src/node/stream-debug-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Emitter, Event } from '@theia/core/lib/common/event';
import { ChildProcess } from 'child_process';
import * as stream from 'stream';
import * as net from 'net';
import { DebugAdapter } from './debug-model';
import { DebugAdapter } from '../common/debug-model';

abstract class StreamDebugAdapter extends DisposableCollection {
private messageReceivedEmitter = new Emitter<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import * as fs from '@theia/core/shared/fs-extra';
import * as path from 'path';
import { DebugAdapterExecutable, DebugAdapterContribution } from '../debug-model';
import { DebugAdapterExecutable, DebugAdapterContribution } from '../../common/debug-model';
import { isWindows, isOSX } from '@theia/core/lib/common/os';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { deepClone } from '@theia/core/lib/common/objects';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// *****************************************************************************

// eslint-disable-next-line @theia/runtime-import-check
import { DebugExtImpl } from '../../../plugin/node/debug/debug';
import { DebugExtImpl } from '../../../plugin/debug/debug-ext';
import { RPCProtocol } from '../../../common/rpc-protocol';

/* eslint-disable @typescript-eslint/no-explicit-any */
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { createAPIFactory } from '../../plugin/plugin-context';
import { EnvExtImpl } from '../../plugin/env';
import { PreferenceRegistryExtImpl } from '../../plugin/preference-registry';
import { ExtPluginApi, ExtPluginApiBackendInitializationFn } from '../../common/plugin-ext-api-contribution';
import { DebugExtImpl } from '../../plugin/node/debug/debug';
import { DebugExtImpl } from '../../plugin/debug/debug-ext';
import { EditorsAndDocumentsExtImpl } from '../../plugin/editors-and-documents';
import { WorkspaceExtImpl } from '../../plugin/workspace';
import { MessageRegistryExt } from '../../plugin/message-registry';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,19 @@ import { Emitter } from '@theia/core/lib/common/event';
import { Path } from '@theia/core/lib/common/path';
import * as theia from '@theia/plugin';
import { URI } from '@theia/core/shared/vscode-uri';
import { Breakpoint } from '../../../common/plugin-api-rpc-model';
import { DebugConfigurationProviderTriggerKind, DebugExt, DebugMain, PLUGIN_RPC_CONTEXT as Ext, TerminalOptionsExt } from '../../../common/plugin-api-rpc';
import { PluginPackageDebuggersContribution } from '../../../common/plugin-protocol';
import { RPCProtocol } from '../../../common/rpc-protocol';
import { CommandRegistryImpl } from '../../command-registry';
import { ConnectionImpl } from '../../../common/connection';
import {
Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range,
DebugAdapterServer, DebugAdapterExecutable, DebugAdapterNamedPipeServer, DebugAdapterInlineImplementation
} from '../../types-impl';
import { resolveDebugAdapterExecutable } from './plugin-debug-adapter-executable-resolver';
import { Breakpoint } from '../../common/plugin-api-rpc-model';
import { DebugConfigurationProviderTriggerKind, DebugExt, DebugMain, PLUGIN_RPC_CONTEXT as Ext, TerminalOptionsExt } from '../../common/plugin-api-rpc';
import { PluginPackageDebuggersContribution } from '../../common/plugin-protocol';
import { RPCProtocol } from '../../common/rpc-protocol';
import { CommandRegistryImpl } from '../command-registry';
import { ConnectionImpl } from '../../common/connection';
import { Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range } from '../types-impl';
import { PluginDebugAdapterSession } from './plugin-debug-adapter-session';
import { connectInlineDebugAdapter, connectPipeDebugAdapter, connectSocketDebugAdapter, startDebugAdapter } from './plugin-debug-adapter-starter';
import { PluginDebugAdapterTracker } from './plugin-debug-adapter-tracker';
import uuid = require('uuid');
import { DebugAdapter } from '@theia/debug/lib/node/debug-model';
import { DebugAdapter } from '@theia/debug/lib/common/debug-model';
import { PluginDebugAdapterCreator } from './plugin-debug-adapter-creator';
import { NodeDebugAdapterCreator } from '../node/debug/plugin-node-debug-adapter-creator';

interface ConfigurationProviderRecord {
handle: number;
Expand All @@ -42,10 +39,7 @@ interface ConfigurationProviderRecord {
}

/* eslint-disable @typescript-eslint/no-explicit-any */
// TODO: rename file to `debug-ext.ts`
/**
* It is supposed to work at node only.
*/

export class DebugExtImpl implements DebugExt {
// debug sessions by sessionId
private sessions = new Map<string, PluginDebugAdapterSession>();
Expand All @@ -60,6 +54,7 @@ export class DebugExtImpl implements DebugExt {
private descriptorFactories = new Map<string, theia.DebugAdapterDescriptorFactory>();
private trackerFactories: [string, theia.DebugAdapterTrackerFactory][] = [];
private contributionPaths = new Map<string, string>();
private contributionTypes = new Map<string, theia.PluginType>();

private connectionExt: ConnectionImpl;
private commandRegistryExt: CommandRegistryImpl;
Expand All @@ -77,6 +72,9 @@ export class DebugExtImpl implements DebugExt {

private readonly _breakpoints = new Map<string, theia.Breakpoint>();

private frontendAdapterCreator = new PluginDebugAdapterCreator();
private backendAdapterCreator = new NodeDebugAdapterCreator();

get breakpoints(): theia.Breakpoint[] {
return [...this._breakpoints.values()];
}
Expand All @@ -102,11 +100,13 @@ export class DebugExtImpl implements DebugExt {
/**
* Registers contributions.
* @param pluginFolder plugin folder path
* @param pluginType plugin type
* @param contributions available debuggers contributions
*/
registerDebuggersContributions(pluginFolder: string, contributions: PluginPackageDebuggersContribution[]): void {
registerDebuggersContributions(pluginFolder: string, pluginType: theia.PluginType, contributions: PluginPackageDebuggersContribution[]): void {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a breaking change in the CHANGELOG.md

contributions.forEach(contribution => {
this.contributionPaths.set(contribution.type, pluginFolder);
this.contributionTypes.set(contribution.type, pluginType);
this.debuggersContributions.set(contribution.type, contribution);
this.proxy.$registerDebuggerContribution({
type: contribution.type,
Expand Down Expand Up @@ -397,43 +397,7 @@ export class DebugExtImpl implements DebugExt {
protected async createDebugAdapter(session: theia.DebugSession, debugConfiguration: theia.DebugConfiguration): Promise<DebugAdapter> {
const executable = await this.resolveDebugAdapterExecutable(debugConfiguration);
const descriptorFactory = this.descriptorFactories.get(session.type);
if (descriptorFactory) {
// 'createDebugAdapterDescriptor' is called at the start of a debug session to provide details about the debug adapter to use.
// These details must be returned as objects of type [DebugAdapterDescriptor](#DebugAdapterDescriptor).
// Currently two types of debug adapters are supported:
// - a debug adapter executable is specified as a command path and arguments (see [DebugAdapterExecutable](#DebugAdapterExecutable)),
// - a debug adapter server reachable via a communication port (see [DebugAdapterServer](#DebugAdapterServer)).
// If the method is not implemented the default behavior is this:
// createDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable) {
// if (typeof session.configuration.debugServer === 'number') {
// return new DebugAdapterServer(session.configuration.debugServer);
// }
// return executable;
// }
// @param session The [debug session](#DebugSession) for which the debug adapter will be used.
// @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists).
const descriptor = await descriptorFactory.createDebugAdapterDescriptor(session, executable);
if (descriptor) {
if (DebugAdapterServer.is(descriptor)) {
return connectSocketDebugAdapter(descriptor);
} else if (DebugAdapterExecutable.is(descriptor)) {
return startDebugAdapter(descriptor);
} else if (DebugAdapterNamedPipeServer.is(descriptor)) {
return connectPipeDebugAdapter(descriptor);
} else if (DebugAdapterInlineImplementation.is(descriptor)) {
return connectInlineDebugAdapter(descriptor);
}
}
}

if ('debugServer' in debugConfiguration) {
return connectSocketDebugAdapter({ port: debugConfiguration.debugServer });
} else {
if (!executable) {
throw new Error('It is not possible to provide debug adapter executable.');
}
return startDebugAdapter(executable);
}
return this.getAdapterCreator(debugConfiguration).createDebugAdapter(session, debugConfiguration, executable, descriptorFactory);
}

protected async resolveDebugAdapterExecutable(debugConfiguration: theia.DebugConfiguration): Promise<theia.DebugAdapterExecutable | undefined> {
Expand All @@ -448,7 +412,7 @@ export class DebugExtImpl implements DebugExt {
} else {
const contributionPath = this.contributionPaths.get(type);
if (contributionPath) {
return resolveDebugAdapterExecutable(contributionPath, contribution);
return this.getAdapterCreator(debugConfiguration).resolveDebugAdapterExecutable(contributionPath, contribution);
}
}
}
Expand All @@ -469,4 +433,9 @@ export class DebugExtImpl implements DebugExt {
index: 0
};
}

private getAdapterCreator(debugConfiguration: theia.DebugConfiguration): PluginDebugAdapterCreator {
const pluginType = this.contributionTypes.get(debugConfiguration.type);
return pluginType === 'frontend' ? this.frontendAdapterCreator : this.backendAdapterCreator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// *****************************************************************************
// Copyright (C) 2022 Arm and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import * as theia from '@theia/plugin';
import { DebugAdapter } from '@theia/debug/lib/common/debug-model';
import { PluginPackageDebuggersContribution } from '../../common';
import { DebugAdapterInlineImplementation } from '../types-impl';
import { InlineDebugAdapter } from '@theia/debug/lib/common/inline-debug-adapter';

export class PluginDebugAdapterCreator {
public async resolveDebugAdapterExecutable(_pluginPath: string, _debuggerContribution: PluginPackageDebuggersContribution): Promise<theia.DebugAdapterExecutable | undefined> {
// Node is required to run the default executable
return undefined;
}

public async createDebugAdapter(
session: theia.DebugSession,
_debugConfiguration: theia.DebugConfiguration,
executable: theia.DebugAdapterExecutable | undefined,
descriptorFactory: theia.DebugAdapterDescriptorFactory | undefined
): Promise<DebugAdapter> {
if (descriptorFactory) {
const descriptor = await descriptorFactory.createDebugAdapterDescriptor(session, executable);
if (descriptor) {
if (DebugAdapterInlineImplementation.is(descriptor)) {
return this.connectInlineDebugAdapter(descriptor);
}
}
}

throw new Error('It is not possible to provide debug adapter executable.');
}

public connectInlineDebugAdapter(adapter: DebugAdapterInlineImplementation): InlineDebugAdapter {
return new InlineDebugAdapter(adapter.implementation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { DebugAdapterSessionImpl } from '@theia/debug/lib/node/debug-adapter-session';
import { DebugAdapterSessionImpl } from '@theia/debug/lib/common/debug-adapter-session';
import * as theia from '@theia/plugin';
import { DebugAdapter } from '@theia/debug/lib/node/debug-model';
import { DebugAdapter } from '@theia/debug/lib/common/debug-model';
import { DebugChannel } from '@theia/debug/lib/common/debug-service';

/* eslint-disable @typescript-eslint/no-explicit-any */
Expand Down
Loading