// ***************************************************************************** // Copyright (C) 2018 Red Hat, Inc. 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-only WITH Classpath-exception-2.0 // ***************************************************************************** import { Channel, Disposable, Emitter, Event } from '@theia/core'; import { ApplicationError } from '@theia/core/lib/common/application-error'; import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema'; import { CommandIdVariables } from '@theia/variable-resolver/lib/common/variable-types'; import { DebugConfiguration } from './debug-configuration'; export interface DebuggerDescription { type: string label: string } /** * Describes a dynamic debug configuration provider with its label and associated types. * Multiple debug types can share the same label (e.g., "Node.js" for "node", "pwa-node", etc.) */ export interface DynamicDebugConfigurationProvider { label: string; types: string[]; } /** * The WS endpoint path to the Debug service. */ export const DebugPath = '/services/debug'; /** * DebugService symbol for DI. */ export const DebugService = Symbol('DebugService'); /** * This service provides functionality to configure and to start a new debug adapter session. * The workflow is the following. If user wants to debug an application and * there is no debug configuration associated with the application then * the list of available providers is requested to create suitable debug configuration. * When configuration is chosen it is possible to alter the configuration * by filling in missing values or by adding/changing/removing attributes. For this purpose the * #resolveDebugConfiguration method is invoked. After that the debug adapter session will be started. */ export interface DebugService extends Disposable { onDidChangeDebuggers?: Event; /** * Finds and returns an array of registered debug types. * @returns An array of registered debug types */ debugTypes(): Promise; getDebuggersForLanguage(language: string): Promise; /** * Provide debugger contributed variables * see "variables" at https://code.visualstudio.com/api/references/contribution-points#contributes.debuggers */ provideDebuggerVariables(debugType: string): Promise; /** * Provides the schema attributes. * @param debugType The registered debug type * @returns An JSON Schema describing the configuration attributes for the given debug type */ getSchemaAttributes(debugType: string): Promise; getConfigurationSnippets(): Promise; /** * Provides initial [debug configuration](#DebugConfiguration). * @param debugType The registered debug type * @returns An array of [debug configurations](#DebugConfiguration) */ provideDebugConfigurations(debugType: string, workspaceFolderUri: string | undefined): Promise; /** * Returns dynamic debug configuration providers grouped by label. * Each entry contains a label and all the types that share that label. * This allows the UI to show human-readable labels and group related types. */ getDynamicDebugConfigurationProviders?(): DynamicDebugConfigurationProvider[]; /** * Returns the types of registered dynamic debug configuration providers * without invoking them. This is a lightweight alternative to * provideDynamicDebugConfigurations when you only need to know what * provider types are available. * @deprecated Use getDynamicDebugConfigurationProviders() instead for proper label support. */ getDynamicDebugConfigurationProviderTypes?(): string[]; /** * @returns A Record of debug configuration provider types and a corresponding dynamic debug configurations array */ provideDynamicDebugConfigurations?(folder?: string): Promise>; /** * Provides dynamic debug configurations for a specific provider type only. * @param type The debug configuration provider type * @param folder The workspace folder URI * @returns An array of debug configurations for the specified type */ provideDynamicDebugConfigurationsByType?(type: string, folder?: string): Promise; /** * Provides a dynamic debug configuration matching the name and the provider debug type */ fetchDynamicDebugConfiguration(name: string, type: string, folder?: string): Promise; /** * Resolves a [debug configuration](#DebugConfiguration) by filling in missing values * or by adding/changing/removing attributes before variable substitution. * @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve. * @returns The resolved debug configuration, undefined or null. */ resolveDebugConfiguration( config: DebugConfiguration, workspaceFolderUri: string | undefined ): Promise; /** * Resolves a [debug configuration](#DebugConfiguration) by filling in missing values * or by adding/changing/removing attributes with substituted variables. * @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve. * @returns The resolved debug configuration, undefined or null. */ resolveDebugConfigurationWithSubstitutedVariables( config: DebugConfiguration, workspaceFolderUri: string | undefined ): Promise; /** * Creates a new [debug adapter session](#DebugAdapterSession). * @param config The resolved [debug configuration](#DebugConfiguration). * @param workspaceFolderUri The workspace folder for this sessions or undefined when folderless * @returns The identifier of the created [debug adapter session](#DebugAdapterSession). */ createDebugSession(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise; /** * Stop a running session for the given session id. */ terminateDebugSession(sessionId: string): Promise; /** * Event handle to indicate when one or more dynamic debug configuration providers * have been registered or unregistered. */ onDidChangeDebugConfigurationProviders: Event; } /** * The endpoint path to the debug adapter session. */ export const DebugAdapterPath = '/services/debug-adapter'; export namespace DebugError { export const NotFound = ApplicationError.declare(-41000, (type: string) => ({ message: `'${type}' debugger type is not supported.`, data: { type } })); } /** * A closeable channel to send debug protocol messages over with error/close handling */ export interface DebugChannel { send(content: string): void; onMessage(cb: (message: string) => void): void; onError(cb: (reason: unknown) => void): void; onClose(cb: (code: number, reason: string) => void): void; close(): void; } /** * A {@link DebugChannel} wrapper implementation that sends and receives messages to/from an underlying {@link Channel}. */ export class ForwardingDebugChannel implements DebugChannel { private onMessageEmitter = new Emitter(); constructor(private readonly underlyingChannel: Channel) { this.underlyingChannel.onMessage(msg => this.onMessageEmitter.fire(msg().readString())); } send(content: string): void { this.underlyingChannel.getWriteBuffer().writeString(content).commit(); } onMessage(cb: (message: string) => void): void { this.onMessageEmitter.event(cb); } onError(cb: (reason: unknown) => void): void { this.underlyingChannel.onError(cb); } onClose(cb: (code: number, reason: string) => void): void { this.underlyingChannel.onClose(event => cb(event.code ?? -1, event.reason)); } close(): void { this.underlyingChannel.close(); this.onMessageEmitter.dispose(); } }