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

Plugin API for debug #3804

Merged
merged 1 commit into from
Dec 22, 2018
Merged

Plugin API for debug #3804

merged 1 commit into from
Dec 22, 2018

Conversation

tolusha
Copy link
Contributor

@tolusha tolusha commented Dec 11, 2018

This PR provides implementation of plugin API for debug

How to test

  1. Download c++ extension into ~/theia-plugins folder.
  2. THEIA_DEFAULT_PLUGINS="local-dir:///home/$USER/theia-plugins"
  3. Start Theia and wait until c++ extension is activated
  4. It is possible to work with c++ debugger

Prepare test file

  1. compile your test file with -g option, for instance: g++ -g test.c++
  2. modify debug configuration to set path to resulted program: "program": "${workspaceFolder}/a.out"
  3. add breakpoints or modify configuration file "stopAtEntry": true

Know issues

1 . Debug adapter sends events in such sequence: 'exited', 'terminated', 'telemetry'.
Since we dispose `debug-session-connection' on 'exited' event we can see some traces in console:

root ERROR [hosted-plugin: 18775] (node:18775) UnhandledPromiseRejectionWarning: Error: the debug session connection is disposed, id: b886d0ce-4622-4a09-a01e-7bd82f55181c
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.checkDisposed (http://localhost:3000/28.bundle.js:2251:19)
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.newEmitter (http://localhost:3000/28.bundle.js:2447:14)
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.getEmitter (http://localhost:3000/28.bundle.js:2441:55)
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.doFire (http://localhost:3000/28.bundle.js:2438:14)
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.handleEvent (http://localhost:3000/28.bundle.js:2421:22)
    at DebugSessionConnection.push.../../packages/debug/lib/browser/debug-session-connection.js.DebugSessionConnection.handleMessage (http://localhost:3000/28.bundle.js:2368:18)
    at PluginMessageReader.callback (http://localhost:3000/28.bundle.js:2273:79)
    at PluginMessageReader.push.../../packages/plugin-ext/lib/common/plugin-message-reader.js.PluginMessageReader.readMessage (http://localhost:3000/74.bundle.js:2391:18)
    at ConnectionMainImpl.<anonymous> (http://localhost:3000/74.bundle.js:4539:53)
    at step (http://localhost:3000/74.bundle.js:4510:23)

screenshot from 2018-12-07 15-47-32

@tolusha tolusha added plug-in system issues related to the plug-in system debug issues that related to debug functionality labels Dec 11, 2018
@tolusha tolusha self-assigned this Dec 11, 2018
@@ -4,6 +4,7 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

Copy link
Contributor

Choose a reason for hiding this comment

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

remove this useless change ?

@@ -97,7 +96,7 @@ export abstract class AbstractVSCodeDebugAdapterContribution implements DebugAda
}

protected async parse(): Promise<VSCodeExtensionPackage> {
let text = (await fs.readFile(this.pckPath)).toString();
let text = (await fs.readFileSync(this.pckPath)).toString();
Copy link
Contributor

Choose a reason for hiding this comment

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

hello, quick question: why fs-extra/readFile has been replaced by fs/readFileSync ?

}

get onDidReceiveDebugSessionCustomEvent(): theia.Event<theia.DebugSessionCustomEvent> {
throw new Error('Debug API works only in plugin container');
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe call a method that throw this message everywhere ? or to use a proxy instead as all methods are throwing errors ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What are the benefits?

Copy link
Contributor

Choose a reason for hiding this comment

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

if new methods are added, then proxy will always be up-to-date and it's avoid 100 exact same lines

constructor(rpc: RPCProtocol) {
this.proxy = rpc.getProxy(Ext.COMMAND_REGISTRY_MAIN);
this.converter = new CommandsConverter(this);

// register internal VS Code commands
Copy link
Contributor

Choose a reason for hiding this comment

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

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

c++ extension use this command to show release notes.
We need to register this command at least with fake handler.
If you have any suggestion you are welcome.

@@ -50,6 +56,7 @@ export class CommandRegistryImpl implements CommandRegistryExt {
this.proxy.$registerCommand(command);

return Disposable.create(() => {
this.commands.delete(command.id);
Copy link
Contributor

Choose a reason for hiding this comment

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

why ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't have to keep command if it is disposed.
some extension (c++ in particular) register/dispose/register the same commands.
If we don't delete command we will fail.

* @param nameOrConfiguration Either the name of a debug or compound configuration or a [DebugConfiguration](#DebugConfiguration) object.
* @return A thenable that resolves when debugging could be successfully started.
*/
export function startDebugging(folder: WorkspaceFolder | undefined, nameOrConfiguration: string | DebugConfiguration): Thenable<boolean>;
Copy link
Contributor

Choose a reason for hiding this comment

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

PromiseLike

* @param key A string.
* @param value A value. MUST not contain cyclic references.
*/
update(key: string, value: any): Thenable<void>;
Copy link
Contributor

Choose a reason for hiding this comment

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

PromiseLike

throw new Error('Debug API works only in plugin container');
}

startDebugging(folder: theia.WorkspaceFolder | undefined, nameOrConfiguration: string | theia.DebugConfiguration): Thenable<boolean> {
Copy link
Contributor

Choose a reason for hiding this comment

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

PromiseLike

this.proxy.$removeBreakpoints(breakpoints);
}

startDebugging(folder: theia.WorkspaceFolder | undefined, nameOrConfiguration: string | theia.DebugConfiguration): Thenable<boolean> {
Copy link
Contributor

Choose a reason for hiding this comment

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

PromiseLike

return value || defaultValue;
}

update(key: string, value: T): Thenable<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

PromiseLike

/**
* Describes what plugin contribution has to provide for a client.
*/
export interface DebugPluginContributor {
Copy link
Member

Choose a reason for hiding this comment

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

debug extension should not have notion of plugins

plugins should be encapsulated into @theia/plugin-ext

import { WebSocketChannel } from '@theia/core/lib/common/messaging/web-socket-channel';
import { DebugConfiguration } from '../common/debug-configuration';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { Disposable } from '@theia/core/lib/common/disposable';
import { MaybePromise } from '@theia/core/src/common/types';
Copy link
Member

Choose a reason for hiding this comment

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

always import from lib


export const INSPECTOR_PORT_DEFAULT = 9229;
export const LEGACY_PORT_DEFAULT = 5858;

@injectable()
export class NodeDebugAdapterContribution extends AbstractVSCodeDebugAdapterContribution {
export class NodeDebugAdapterContribution implements DebugAdapterContribution {
Copy link
Member

Choose a reason for hiding this comment

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

Can you elaborate why it cannot extend VSCodeDebugAdapterContribution? the same for node2 and java

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In case of extension I have to use inversify.
But in this case I can't use it in plugin-ext

Copy link
Member

@akosyakov akosyakov Dec 14, 2018

Choose a reason for hiding this comment

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

I think VsCodePluginScanner should be improved to handle vscode extension localization generally and support debugger relevant contributions. The plugin extension then should use PluginModel to provide DebugAdapterContribution. Maybe some code should be copied there from VSCodeDebugAdapterContribution to achieve it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@akosyakov resolved
2aa725a

protected readonly debugPreferences: DebugPreferences;

protected readonly onDidContributionAddEmitter = new Emitter<string>();
readonly onDidContributionAdd: Event<string> = this.onDidContributionAddEmitter.event;
Copy link
Member

Choose a reason for hiding this comment

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

* Session factory for a client debug session that communicates with debug adapter contributed as plugin.
* The main difference is to use a connection factory that creates [IWebSocket](#IWebSocket) over Rpc channel.
*/
class PluginDebugSessionFactory implements DebugSessionFactory {
Copy link
Member

@akosyakov akosyakov Dec 12, 2018

Choose a reason for hiding this comment

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

a class should go to its own file, a file name should be a class name

we try not to put several classes in one file with a random name, also we try to avoid classes with the same name in the repo

it is to easy navigation

@tolusha tolusha added dap debug adapter protocol vscode issues related to VSCode compatibility Team: Che-Languages issues regarding the che-languages team labels Dec 12, 2018
@akosyakov
Copy link
Member

akosyakov commented Dec 12, 2018

It introduces implicit dependencies from the debug to the plugin extension. Dependencies should be only in on direction from the plugin to debug extension. The debug extension should not have notion of plugins or plugin contributions. The plugin extension can rebind and customize services from the debug extension to add this notion.

@akosyakov
Copy link
Member

Functional-wise, after battling with g++/gdb I was able to run it eventually :) It works for me nicely and I did not find any breaking behavior changes.

}

async resolveDebugConfiguration(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration> {
const contributor = this.pluginContributors.get(config.type);
Copy link
Member

@akosyakov akosyakov Dec 13, 2018

Choose a reason for hiding this comment

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

it is bogus, all debug providers should participate in the resolution of any DebugConfiguration, regardless of whether they come from extensions or plugins. Like in DebugAdapterContributionRegistry.resolveDebugConfiguration. I think the whole integration should happen behind DebugService on the level of debug adapter contributions that the code in DebugService and DebugAdapterContributionRegistry is reused.

}
}

class DebugPluginContribution extends VSCodeDebugAdapterContribution {
Copy link
Member

@akosyakov akosyakov Dec 13, 2018

Choose a reason for hiding this comment

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

it looks strange, plugins should not rely on VSCodeDebugAdapterContribution from the debug extension, but should read metadata from plugins, the same way as metadata for commands and menu items and so on, read by the plugin extension.

I hoped that this PR will fix #3771 (comment) by improving localization of metadata from VS Code extensions.

@tolusha
Copy link
Contributor Author

tolusha commented Dec 14, 2018

@akosyakov I've addressed all your remarks.

Copy link
Contributor

@svenefftinge svenefftinge left a comment

Choose a reason for hiding this comment

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

LGTM, whatever Anton's concern was can be fixed after merge as well. There is . a missing ,in plugin-api.ts and would be good if you could squash the commits.

@tolusha tolusha force-pushed the ab/DebugPluginApi branch 4 times, most recently from 385dd3f to 45dfe07 Compare December 22, 2018 07:58
Signed-off-by: Anatoliy Bazko <abazko@redhat.com>
@tolusha tolusha merged commit 9cf1895 into master Dec 22, 2018
@tolusha tolusha deleted the ab/DebugPluginApi branch December 22, 2018 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dap debug adapter protocol debug issues that related to debug functionality plug-in system issues related to the plug-in system Team: Che-Languages issues regarding the che-languages team vscode issues related to VSCode compatibility
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants