mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-03 09:35:40 -05:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -13,7 +13,7 @@ import { IDebugAdapter } from 'vs/workbench/contrib/debug/common/debug';
|
||||
export abstract class AbstractDebugAdapter implements IDebugAdapter {
|
||||
|
||||
private sequence: number;
|
||||
private pendingRequests: Map<number, (e: DebugProtocol.Response) => void>;
|
||||
private pendingRequests = new Map<number, (e: DebugProtocol.Response) => void>();
|
||||
private requestCallback: (request: DebugProtocol.Request) => void;
|
||||
private eventCallback: (request: DebugProtocol.Event) => void;
|
||||
private messageCallback: (message: DebugProtocol.ProtocolMessage) => void;
|
||||
@@ -22,7 +22,6 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter {
|
||||
|
||||
constructor() {
|
||||
this.sequence = 1;
|
||||
this.pendingRequests = new Map();
|
||||
this._onError = new Emitter<Error>();
|
||||
this._onExit = new Emitter<number>();
|
||||
}
|
||||
@@ -139,7 +138,7 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter {
|
||||
|
||||
protected cancelPending() {
|
||||
const pending = this.pendingRequests;
|
||||
this.pendingRequests = new Map();
|
||||
this.pendingRequests.clear();
|
||||
setTimeout(_ => {
|
||||
pending.forEach((callback, request_seq) => {
|
||||
const err: DebugProtocol.Response = {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel as EditorIModel } from 'vs/editor/common/model';
|
||||
import { IEditor } from 'vs/workbench/common/editor';
|
||||
import { IEditor, ITextEditor } from 'vs/workbench/common/editor';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { CompletionItem } from 'vs/editor/common/modes';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
@@ -25,6 +25,8 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { ITerminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IExternalTerminalSettings } from 'vs/workbench/contrib/externalTerminal/common/externalTerminal';
|
||||
|
||||
export const VIEWLET_ID = 'workbench.view.debug';
|
||||
export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(VIEWLET_ID);
|
||||
@@ -54,6 +56,7 @@ export const CONTEXT_LOADED_SCRIPTS_ITEM_TYPE = new RawContextKey<string>('loade
|
||||
export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey<boolean>('focusedSessionIsAttach', false);
|
||||
export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey<boolean>('stepBackSupported', false);
|
||||
export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey<boolean>('restartFrameSupported', false);
|
||||
export const CONTEXT_JUMP_TO_CURSOR_SUPPORTED = new RawContextKey<boolean>('jumpToCursorSupported', false);
|
||||
|
||||
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
|
||||
export const DEBUG_SCHEME = 'debug';
|
||||
@@ -222,6 +225,9 @@ export interface IDebugSession extends ITreeElement {
|
||||
setVariable(variablesReference: number | undefined, name: string, value: string): Promise<DebugProtocol.SetVariableResponse>;
|
||||
loadSource(resource: uri): Promise<DebugProtocol.SourceResponse>;
|
||||
getLoadedSources(): Promise<Source[]>;
|
||||
|
||||
gotoTargets(source: DebugProtocol.Source, line: number, column?: number): Promise<DebugProtocol.GotoTargetsResponse>;
|
||||
goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse>;
|
||||
}
|
||||
|
||||
export interface IThread extends ITreeElement {
|
||||
@@ -296,9 +302,10 @@ export interface IStackFrame extends ITreeElement {
|
||||
getScopes(): Promise<IScope[]>;
|
||||
getMostSpecificScopes(range: IRange): Promise<ReadonlyArray<IScope>>;
|
||||
getSpecificSourceName(): string;
|
||||
forgetScopes(): void;
|
||||
restart(): Promise<any>;
|
||||
toString(): string;
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean): Promise<any>;
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean): Promise<ITextEditor | null>;
|
||||
}
|
||||
|
||||
export interface IEnablement extends ITreeElement {
|
||||
@@ -339,6 +346,7 @@ export interface IBreakpoint extends IBaseBreakpoint {
|
||||
readonly endColumn?: number;
|
||||
readonly message?: string;
|
||||
readonly adapterData: any;
|
||||
readonly sessionAgnosticData: { lineNumber: number, column: number | undefined };
|
||||
}
|
||||
|
||||
export interface IFunctionBreakpoint extends IBaseBreakpoint {
|
||||
@@ -432,6 +440,7 @@ export interface IDebugConfiguration {
|
||||
fontSize: number;
|
||||
fontFamily: string;
|
||||
lineHeight: number;
|
||||
wordWrap: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -481,7 +490,7 @@ export interface IDebugAdapter extends IDisposable {
|
||||
startSession(): Promise<void>;
|
||||
sendMessage(message: DebugProtocol.ProtocolMessage): void;
|
||||
sendResponse(response: DebugProtocol.Response): void;
|
||||
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timemout?: number): void;
|
||||
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void;
|
||||
stopSession(): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -568,11 +577,7 @@ export interface ITerminalLauncher {
|
||||
}
|
||||
|
||||
export interface ITerminalSettings {
|
||||
external: {
|
||||
windowsExec: string,
|
||||
osxExec: string,
|
||||
linuxExec: string
|
||||
};
|
||||
external: IExternalTerminalSettings;
|
||||
integrated: ITerminalConfiguration;
|
||||
}
|
||||
|
||||
@@ -717,7 +722,7 @@ export interface IDebugService {
|
||||
/**
|
||||
* Updates the breakpoints.
|
||||
*/
|
||||
updateBreakpoints(uri: uri, data: { [id: string]: IBreakpointUpdateData }, sendOnResourceSaved: boolean): void;
|
||||
updateBreakpoints(uri: uri, data: Map<string, IBreakpointUpdateData>, sendOnResourceSaved: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* Enables or disables all breakpoints. If breakpoint is passed only enables or disables the passed breakpoint.
|
||||
@@ -829,3 +834,14 @@ export interface IDebugEditorContribution extends IEditorContribution {
|
||||
closeBreakpointWidget(): void;
|
||||
addLaunchConfiguration(): Promise<any>;
|
||||
}
|
||||
|
||||
// temporary debug helper service
|
||||
|
||||
export const DEBUG_HELPER_SERVICE_ID = 'debugHelperService';
|
||||
export const IDebugHelperService = createDecorator<IDebugHelperService>(DEBUG_HELPER_SERVICE_ID);
|
||||
|
||||
export interface IDebugHelperService {
|
||||
_serviceBrand: any;
|
||||
|
||||
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
|
||||
});
|
||||
} else {
|
||||
// create text model
|
||||
const mime = response.body.mimeType || guessMimeTypes(resource.path)[0];
|
||||
const mime = response.body.mimeType || guessMimeTypes(resource)[0];
|
||||
const languageSelection = this.modeService.create(mime);
|
||||
return this.modelService.createModel(response.body.content, languageSelection, resource);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import { commonSuffixLength } from 'vs/base/common/strings';
|
||||
import { posix } from 'vs/base/common/path';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextEditor } from 'vs/workbench/common/editor';
|
||||
|
||||
export class SimpleReplElement implements IReplElement {
|
||||
constructor(
|
||||
@@ -89,7 +90,7 @@ export class RawObjectReplElement implements IExpression {
|
||||
|
||||
export class ExpressionContainer implements IExpressionContainer {
|
||||
|
||||
public static allValues: Map<string, string> = new Map<string, string>();
|
||||
public static allValues = new Map<string, string>();
|
||||
// Use chunks to support variable paging #9537
|
||||
private static readonly BASE_CHUNK_SIZE = 100;
|
||||
|
||||
@@ -123,7 +124,7 @@ export class ExpressionContainer implements IExpressionContainer {
|
||||
return this.children;
|
||||
}
|
||||
|
||||
private doGetChildren(): Promise<IExpression[]> {
|
||||
private async doGetChildren(): Promise<IExpression[]> {
|
||||
if (!this.hasChildren) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
@@ -133,29 +134,28 @@ export class ExpressionContainer implements IExpressionContainer {
|
||||
}
|
||||
|
||||
// Check if object has named variables, fetch them independent from indexed variables #9670
|
||||
const childrenThenable = !!this.namedVariables ? this.fetchVariables(undefined, undefined, 'named') : Promise.resolve([]);
|
||||
return childrenThenable.then(childrenArray => {
|
||||
// Use a dynamic chunk size based on the number of elements #9774
|
||||
let chunkSize = ExpressionContainer.BASE_CHUNK_SIZE;
|
||||
while (!!this.indexedVariables && this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) {
|
||||
chunkSize *= ExpressionContainer.BASE_CHUNK_SIZE;
|
||||
const children = this.namedVariables ? await this.fetchVariables(undefined, undefined, 'named') : [];
|
||||
|
||||
// Use a dynamic chunk size based on the number of elements #9774
|
||||
let chunkSize = ExpressionContainer.BASE_CHUNK_SIZE;
|
||||
while (!!this.indexedVariables && this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) {
|
||||
chunkSize *= ExpressionContainer.BASE_CHUNK_SIZE;
|
||||
}
|
||||
|
||||
if (!!this.indexedVariables && this.indexedVariables > chunkSize) {
|
||||
// There are a lot of children, create fake intermediate values that represent chunks #9537
|
||||
const numberOfChunks = Math.ceil(this.indexedVariables / chunkSize);
|
||||
for (let i = 0; i < numberOfChunks; i++) {
|
||||
const start = (this.startOfVariables || 0) + i * chunkSize;
|
||||
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
|
||||
children.push(new Variable(this.session, this, this.reference, `[${start}..${start + count - 1}]`, '', '', undefined, count, { kind: 'virtual' }, undefined, true, start));
|
||||
}
|
||||
|
||||
if (!!this.indexedVariables && this.indexedVariables > chunkSize) {
|
||||
// There are a lot of children, create fake intermediate values that represent chunks #9537
|
||||
const numberOfChunks = Math.ceil(this.indexedVariables / chunkSize);
|
||||
for (let i = 0; i < numberOfChunks; i++) {
|
||||
const start = (this.startOfVariables || 0) + i * chunkSize;
|
||||
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
|
||||
childrenArray.push(new Variable(this.session, this, this.reference, `[${start}..${start + count - 1}]`, '', '', undefined, count, { kind: 'virtual' }, undefined, true, start));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
return childrenArray;
|
||||
}
|
||||
|
||||
return this.fetchVariables(this.startOfVariables, this.indexedVariables, 'indexed')
|
||||
.then(variables => childrenArray.concat(variables));
|
||||
});
|
||||
const variables = await this.fetchVariables(this.startOfVariables, this.indexedVariables, 'indexed');
|
||||
return children.concat(variables);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -213,7 +213,7 @@ export class Expression extends ExpressionContainer implements IExpression {
|
||||
}
|
||||
}
|
||||
|
||||
evaluate(session: IDebugSession | undefined, stackFrame: IStackFrame | undefined, context: string): Promise<void> {
|
||||
async evaluate(session: IDebugSession | undefined, stackFrame: IStackFrame | undefined, context: string): Promise<void> {
|
||||
if (!session || (!stackFrame && context !== 'repl')) {
|
||||
this.value = context === 'repl' ? nls.localize('startDebugFirst', "Please start a debug session to evaluate expressions") : Expression.DEFAULT_VALUE;
|
||||
this.available = false;
|
||||
@@ -223,7 +223,8 @@ export class Expression extends ExpressionContainer implements IExpression {
|
||||
}
|
||||
|
||||
this.session = session;
|
||||
return session.evaluate(this.name, stackFrame ? stackFrame.frameId : undefined, context).then(response => {
|
||||
try {
|
||||
const response = await session.evaluate(this.name, stackFrame ? stackFrame.frameId : undefined, context);
|
||||
this.available = !!(response && response.body);
|
||||
if (response && response.body) {
|
||||
this.value = response.body.result;
|
||||
@@ -232,11 +233,11 @@ export class Expression extends ExpressionContainer implements IExpression {
|
||||
this.indexedVariables = response.body.indexedVariables;
|
||||
this.type = response.body.type || this.type;
|
||||
}
|
||||
}, err => {
|
||||
this.value = err.message;
|
||||
} catch (e) {
|
||||
this.value = e.message;
|
||||
this.available = false;
|
||||
this.reference = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@@ -267,12 +268,13 @@ export class Variable extends ExpressionContainer implements IExpression {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
setVariable(value: string): Promise<any> {
|
||||
async setVariable(value: string): Promise<any> {
|
||||
if (!this.session) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return this.session.setVariable((<ExpressionContainer>this.parent).reference, this.name, value).then(response => {
|
||||
try {
|
||||
const response = await this.session.setVariable((<ExpressionContainer>this.parent).reference, this.name, value);
|
||||
if (response && response.body) {
|
||||
this.value = response.body.value;
|
||||
this.type = response.body.type || this.type;
|
||||
@@ -280,9 +282,9 @@ export class Variable extends ExpressionContainer implements IExpression {
|
||||
this.namedVariables = response.body.namedVariables;
|
||||
this.indexedVariables = response.body.indexedVariables;
|
||||
}
|
||||
}, err => {
|
||||
} catch (err) {
|
||||
this.errorMessage = err.message;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@@ -302,7 +304,7 @@ export class Scope extends ExpressionContainer implements IScope {
|
||||
indexedVariables?: number,
|
||||
public range?: IRange
|
||||
) {
|
||||
super(stackFrame.thread.session, reference, `scope:${stackFrame.getId()}:${name}:${index}`, namedVariables, indexedVariables);
|
||||
super(stackFrame.thread.session, reference, `scope:${name}:${index}`, namedVariables, indexedVariables);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@@ -312,7 +314,7 @@ export class Scope extends ExpressionContainer implements IScope {
|
||||
|
||||
export class StackFrame implements IStackFrame {
|
||||
|
||||
private scopes: Promise<Scope[]> | null;
|
||||
private scopes: Promise<Scope[]> | undefined;
|
||||
|
||||
constructor(
|
||||
public thread: IThread,
|
||||
@@ -322,9 +324,7 @@ export class StackFrame implements IStackFrame {
|
||||
public presentationHint: string | undefined,
|
||||
public range: IRange,
|
||||
private index: number
|
||||
) {
|
||||
this.scopes = null;
|
||||
}
|
||||
) { }
|
||||
|
||||
getId(): string {
|
||||
return `stackframe:${this.thread.getId()}:${this.frameId}:${this.index}`;
|
||||
@@ -380,6 +380,10 @@ export class StackFrame implements IStackFrame {
|
||||
return this.thread.session.restartFrame(this.frameId, this.thread.threadId);
|
||||
}
|
||||
|
||||
forgetScopes(): void {
|
||||
this.scopes = undefined;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
const lineNumberToString = typeof this.range.startLineNumber === 'number' ? `:${this.range.startLineNumber}` : '';
|
||||
const sourceToString = `${this.source.inMemory ? this.source.name : this.source.uri.fsPath}${lineNumberToString}`;
|
||||
@@ -387,7 +391,7 @@ export class StackFrame implements IStackFrame {
|
||||
return sourceToString === UNKNOWN_SOURCE_LABEL ? this.name : `${this.name} (${sourceToString})`;
|
||||
}
|
||||
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<any> {
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | null> {
|
||||
return !this.source.available ? Promise.resolve(null) :
|
||||
this.source.openInEditor(editorService, this.range, preserveFocus, sideBySide, pinned);
|
||||
}
|
||||
@@ -659,6 +663,13 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
|
||||
return data ? data.endColumn : undefined;
|
||||
}
|
||||
|
||||
get sessionAgnosticData(): { lineNumber: number, column: number | undefined } {
|
||||
return {
|
||||
lineNumber: this._lineNumber,
|
||||
column: this._column
|
||||
};
|
||||
}
|
||||
|
||||
setSessionData(sessionId: string, data: DebugProtocol.Breakpoint): void {
|
||||
super.setSessionData(sessionId, data);
|
||||
if (!this._adapterData) {
|
||||
@@ -954,10 +965,10 @@ export class DebugModel implements IDebugModel {
|
||||
this._onDidChangeBreakpoints.fire({ removed: toRemove });
|
||||
}
|
||||
|
||||
updateBreakpoints(data: { [id: string]: IBreakpointUpdateData }): void {
|
||||
updateBreakpoints(data: Map<string, IBreakpointUpdateData>): void {
|
||||
const updated: IBreakpoint[] = [];
|
||||
this.breakpoints.forEach(bp => {
|
||||
const bpData = data[bp.getId()];
|
||||
const bpData = data.get(bp.getId());
|
||||
if (bpData) {
|
||||
bp.update(bpData);
|
||||
updated.push(bp);
|
||||
@@ -967,15 +978,15 @@ export class DebugModel implements IDebugModel {
|
||||
this._onDidChangeBreakpoints.fire({ changed: updated });
|
||||
}
|
||||
|
||||
setBreakpointSessionData(sessionId: string, data: { [id: string]: DebugProtocol.Breakpoint }): void {
|
||||
setBreakpointSessionData(sessionId: string, data: Map<string, DebugProtocol.Breakpoint>): void {
|
||||
this.breakpoints.forEach(bp => {
|
||||
const bpData = data[bp.getId()];
|
||||
const bpData = data.get(bp.getId());
|
||||
if (bpData) {
|
||||
bp.setSessionData(sessionId, bpData);
|
||||
}
|
||||
});
|
||||
this.functionBreakpoints.forEach(fbp => {
|
||||
const fbpData = data[fbp.getId()];
|
||||
const fbpData = data.get(fbp.getId());
|
||||
if (fbpData) {
|
||||
fbp.setSessionData(sessionId, fbpData);
|
||||
}
|
||||
|
||||
@@ -240,6 +240,8 @@ declare module DebugProtocol {
|
||||
'attachForSuspendedLaunch': A project launcher component has launched a new process in a suspended state and then asked the debugger to attach.
|
||||
*/
|
||||
startMethod?: 'launch' | 'attach' | 'attachForSuspendedLaunch';
|
||||
/** The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display. */
|
||||
pointerSize?: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -323,6 +325,8 @@ declare module DebugProtocol {
|
||||
supportsVariablePaging?: boolean;
|
||||
/** Client supports the runInTerminal request. */
|
||||
supportsRunInTerminalRequest?: boolean;
|
||||
/** Client supports memory references. */
|
||||
supportsMemoryReferences?: boolean;
|
||||
}
|
||||
|
||||
/** Response to 'initialize' request. */
|
||||
@@ -1047,6 +1051,8 @@ declare module DebugProtocol {
|
||||
The client can use this optional information to present the variables in a paged UI and fetch them in chunks.
|
||||
*/
|
||||
indexedVariables?: number;
|
||||
/** Memory reference to a location appropriate for this result. For pointer type eval results, this is generally a reference to the memory address contained in the pointer. */
|
||||
memoryReference?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1202,6 +1208,66 @@ declare module DebugProtocol {
|
||||
};
|
||||
}
|
||||
|
||||
/** ReadMemory request; value of command field is 'readMemory'.
|
||||
Reads bytes from memory at the provided location.
|
||||
*/
|
||||
export interface ReadMemoryRequest extends Request {
|
||||
// command: 'readMemory';
|
||||
arguments: ReadMemoryArguments;
|
||||
}
|
||||
|
||||
/** Arguments for 'readMemory' request. */
|
||||
export interface ReadMemoryArguments {
|
||||
/** Memory reference to the base location from which data should be read. */
|
||||
memoryReference: string;
|
||||
/** Optional offset (in bytes) to be applied to the reference location before reading data. Can be negative. */
|
||||
offset?: number;
|
||||
/** Number of bytes to read at the specified location and offset. */
|
||||
count: number;
|
||||
}
|
||||
|
||||
/** Response to 'readMemory' request. */
|
||||
export interface ReadMemoryResponse extends Response {
|
||||
body?: {
|
||||
/** The address of the first byte of data returned. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. */
|
||||
address: string;
|
||||
/** The number of unreadable bytes encountered after the last successfully read byte. This can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed. */
|
||||
unreadableBytes?: number;
|
||||
/** The bytes read from memory, encoded using base64. */
|
||||
data?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/** Disassemble request; value of command field is 'disassemble'.
|
||||
Disassembles code stored at the provided location.
|
||||
*/
|
||||
export interface DisassembleRequest extends Request {
|
||||
// command: 'disassemble';
|
||||
arguments: DisassembleArguments;
|
||||
}
|
||||
|
||||
/** Arguments for 'disassemble' request. */
|
||||
export interface DisassembleArguments {
|
||||
/** Memory reference to the base location containing the instructions to disassemble. */
|
||||
memoryReference: string;
|
||||
/** Optional offset (in bytes) to be applied to the reference location before disassembling. Can be negative. */
|
||||
offset?: number;
|
||||
/** Optional offset (in instructions) to be applied after the byte offset (if any) before disassembling. Can be negative. */
|
||||
instructionOffset?: number;
|
||||
/** Number of instructions to disassemble starting at the specified location and offset. An adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value. */
|
||||
instructionCount: number;
|
||||
/** If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. */
|
||||
resolveSymbols?: boolean;
|
||||
}
|
||||
|
||||
/** Response to 'disassemble' request. */
|
||||
export interface DisassembleResponse extends Response {
|
||||
body?: {
|
||||
/** The list of disassembled instructions. */
|
||||
instructions: DisassembledInstruction[];
|
||||
};
|
||||
}
|
||||
|
||||
/** Information about the capabilities of a debug adapter. */
|
||||
export interface Capabilities {
|
||||
/** The debug adapter supports the 'configurationDone' request. */
|
||||
@@ -1258,6 +1324,10 @@ declare module DebugProtocol {
|
||||
supportsTerminateRequest?: boolean;
|
||||
/** The debug adapter supports data breakpoints. */
|
||||
supportsDataBreakpoints?: boolean;
|
||||
/** The debug adapter supports the 'readMemory' request. */
|
||||
supportsReadMemoryRequest?: boolean;
|
||||
/** The debug adapter supports the 'disassemble' request. */
|
||||
supportsDisassembleRequest?: boolean;
|
||||
}
|
||||
|
||||
/** An ExceptionBreakpointsFilter is shown in the UI as an option for configuring how exceptions are dealt with. */
|
||||
@@ -1393,6 +1463,8 @@ declare module DebugProtocol {
|
||||
endLine?: number;
|
||||
/** An optional end column of the range covered by the stack frame. */
|
||||
endColumn?: number;
|
||||
/** Optional memory reference for the current instruction pointer in this frame. */
|
||||
instructionPointerReference?: string;
|
||||
/** The module associated with this frame, if any. */
|
||||
moduleId?: number | string;
|
||||
/** An optional hint for how to present this frame in the UI. A value of 'label' can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of 'subtle' can be used to change the appearance of a frame in a 'subtle' way. */
|
||||
@@ -1401,8 +1473,16 @@ declare module DebugProtocol {
|
||||
|
||||
/** A Scope is a named container for variables. Optionally a scope can map to a source or a range within a source. */
|
||||
export interface Scope {
|
||||
/** Name of the scope such as 'Arguments', 'Locals'. */
|
||||
/** Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. */
|
||||
name: string;
|
||||
/** An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI.
|
||||
Values:
|
||||
'arguments': Scope contains method arguments.
|
||||
'locals': Scope contains local variables.
|
||||
'registers': Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request.
|
||||
etc.
|
||||
*/
|
||||
presentationHint?: string;
|
||||
/** The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest. */
|
||||
variablesReference: number;
|
||||
/** The number of named variables in this scope.
|
||||
@@ -1455,6 +1535,8 @@ declare module DebugProtocol {
|
||||
The client can use this optional information to present the children in a paged UI and fetch them in chunks.
|
||||
*/
|
||||
indexedVariables?: number;
|
||||
/** Optional memory reference for the variable if the variable represents executable code, such as a function pointer. */
|
||||
memoryReference?: string;
|
||||
}
|
||||
|
||||
/** Optional properties of a variable that can be used to determine how to render the variable in the UI. */
|
||||
@@ -1576,6 +1658,8 @@ declare module DebugProtocol {
|
||||
endLine?: number;
|
||||
/** An optional end column of the range covered by the goto target. */
|
||||
endColumn?: number;
|
||||
/** Optional memory reference for the instruction pointer value represented by this target. */
|
||||
instructionPointerReference?: string;
|
||||
}
|
||||
|
||||
/** CompletionItems are the suggestions returned from the CompletionsRequest. */
|
||||
@@ -1673,5 +1757,27 @@ declare module DebugProtocol {
|
||||
/** Details of the exception contained by this exception, if any. */
|
||||
innerException?: ExceptionDetails[];
|
||||
}
|
||||
|
||||
/** Represents a single disassembled instruction. */
|
||||
export interface DisassembledInstruction {
|
||||
/** The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. */
|
||||
address: string;
|
||||
/** Optional raw bytes representing the instruction and its operands, in an implementation-defined format. */
|
||||
instructionBytes?: string;
|
||||
/** Text representing the instruction and its operands, in an implementation-defined format. */
|
||||
instruction: string;
|
||||
/** Name of the symbol that correponds with the location of this instruction, if any. */
|
||||
symbol?: string;
|
||||
/** Source location that corresponds to this instruction, if any. Should always be set (if available) on the first instruction returned, but can be omitted afterwards if this instruction maps to the same source file as the previous instruction. */
|
||||
location?: Source;
|
||||
/** The line within the source location that corresponds to this instruction, if any. */
|
||||
line?: number;
|
||||
/** The column within the line that corresponds to this instruction, if any. */
|
||||
column?: number;
|
||||
/** The end line of the range that corresponds to this instruction, if any. */
|
||||
endLine?: number;
|
||||
/** The end column of the range that corresponds to this instruction, if any. */
|
||||
endColumn?: number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE
|
||||
jsonSchema: {
|
||||
description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'),
|
||||
type: 'array',
|
||||
defaultSnippets: [{ body: [{ type: '', extensions: [] }] }],
|
||||
defaultSnippets: [{ body: [{ type: '' }] }],
|
||||
items: {
|
||||
additionalProperties: false,
|
||||
type: 'object',
|
||||
defaultSnippets: [{ body: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [''] } } }],
|
||||
properties: {
|
||||
@@ -47,7 +48,7 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE
|
||||
type: 'array'
|
||||
},
|
||||
variables: {
|
||||
description: nls.localize('vscode.extension.contributes.debuggers.variables', "Mapping from interactive variables (e.g ${action.pickProcess}) in `launch.json` to a command."),
|
||||
description: nls.localize('vscode.extension.contributes.debuggers.variables', "Mapping from interactive variables (e.g. ${action.pickProcess}) in `launch.json` to a command."),
|
||||
type: 'object'
|
||||
},
|
||||
initialConfigurations: {
|
||||
@@ -118,6 +119,7 @@ export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registe
|
||||
defaultSnippets: [{ body: [{ language: '' }] }],
|
||||
items: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
defaultSnippets: [{ body: { language: '' } }],
|
||||
properties: {
|
||||
language: {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { IRange } from 'vs/editor/common/core/range';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { ITextEditor } from 'vs/workbench/common/editor';
|
||||
|
||||
export const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Source");
|
||||
|
||||
@@ -25,7 +26,6 @@ export const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Sourc
|
||||
* | | | |
|
||||
* scheme source.path session id source.reference
|
||||
*
|
||||
* the arbitrary_path and the session id are encoded with 'encodeURIComponent'
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,11 @@ export class Source {
|
||||
}
|
||||
|
||||
if (typeof this.raw.sourceReference === 'number' && this.raw.sourceReference > 0) {
|
||||
this.uri = uri.parse(`${DEBUG_SCHEME}:${encodeURIComponent(path)}?session=${encodeURIComponent(sessionId)}&ref=${this.raw.sourceReference}`);
|
||||
this.uri = uri.from({
|
||||
scheme: DEBUG_SCHEME,
|
||||
path,
|
||||
query: `session=${sessionId}&ref=${this.raw.sourceReference}`
|
||||
});
|
||||
} else {
|
||||
if (isUri(path)) { // path looks like a uri
|
||||
this.uri = uri.parse(path);
|
||||
@@ -59,7 +63,11 @@ export class Source {
|
||||
} else {
|
||||
// path is relative: since VS Code cannot deal with this by itself
|
||||
// create a debug url that will result in a DAP 'source' request when the url is resolved.
|
||||
this.uri = uri.parse(`${DEBUG_SCHEME}:${encodeURIComponent(path)}?session=${encodeURIComponent(sessionId)}`);
|
||||
this.uri = uri.from({
|
||||
scheme: DEBUG_SCHEME,
|
||||
path,
|
||||
query: `session=${sessionId}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,14 +93,13 @@ export class Source {
|
||||
return this.uri.scheme === DEBUG_SCHEME;
|
||||
}
|
||||
|
||||
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<any> {
|
||||
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | null> {
|
||||
return !this.available ? Promise.resolve(null) : editorService.openEditor({
|
||||
resource: this.uri,
|
||||
description: this.origin,
|
||||
options: {
|
||||
preserveFocus,
|
||||
selection,
|
||||
revealIfVisible: true,
|
||||
revealIfOpened: true,
|
||||
revealInCenterIfOutsideViewport: true,
|
||||
pinned: pinned || (!preserveFocus && !this.inMemory)
|
||||
@@ -118,7 +125,7 @@ export class Source {
|
||||
if (pair.length === 2) {
|
||||
switch (pair[0]) {
|
||||
case 'session':
|
||||
sessionId = decodeURIComponent(pair[1]);
|
||||
sessionId = pair[1];
|
||||
break;
|
||||
case 'ref':
|
||||
sourceReference = parseInt(pair[1]);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
|
||||
@@ -27,6 +27,7 @@ export class ViewModel implements IViewModel {
|
||||
private stepBackSupportedContextKey: IContextKey<boolean>;
|
||||
private focusedSessionIsAttach: IContextKey<boolean>;
|
||||
private restartFrameSupportedContextKey: IContextKey<boolean>;
|
||||
private jumpToCursorSupported: IContextKey<boolean>;
|
||||
|
||||
constructor(contextKeyService: IContextKeyService) {
|
||||
this._onDidFocusSession = new Emitter<IDebugSession | undefined>();
|
||||
@@ -39,6 +40,7 @@ export class ViewModel implements IViewModel {
|
||||
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
|
||||
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
|
||||
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
|
||||
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -68,6 +70,7 @@ export class ViewModel implements IViewModel {
|
||||
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
|
||||
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
|
||||
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
|
||||
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
|
||||
const attach = !!session && !session.parentSession && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration);
|
||||
this.focusedSessionIsAttach.set(attach);
|
||||
|
||||
|
||||
281
src/vs/workbench/contrib/debug/common/debugger.ts
Normal file
281
src/vs/workbench/contrib/debug/common/debugger.ts
Normal file
@@ -0,0 +1,281 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IConfig, IDebuggerContribution, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import * as ConfigurationResolverUtils from 'vs/workbench/services/configurationResolver/common/configurationResolverUtils';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class Debugger implements IDebugger {
|
||||
|
||||
private debuggerContribution: IDebuggerContribution;
|
||||
private mergedExtensionDescriptions: IExtensionDescription[] = [];
|
||||
private mainExtensionDescription: IExtensionDescription | undefined;
|
||||
|
||||
constructor(private configurationManager: IConfigurationManager, dbgContribution: IDebuggerContribution, extensionDescription: IExtensionDescription,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService private readonly resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IDebugHelperService private readonly debugHelperService: IDebugHelperService
|
||||
) {
|
||||
this.debuggerContribution = { type: dbgContribution.type };
|
||||
this.merge(dbgContribution, extensionDescription);
|
||||
}
|
||||
|
||||
public merge(otherDebuggerContribution: IDebuggerContribution, extensionDescription: IExtensionDescription): void {
|
||||
|
||||
/**
|
||||
* Copies all properties of source into destination. The optional parameter "overwrite" allows to control
|
||||
* if existing non-structured properties on the destination should be overwritten or not. Defaults to true (overwrite).
|
||||
*/
|
||||
function mixin(destination: any, source: any, overwrite: boolean, level = 0): any {
|
||||
|
||||
if (!isObject(destination)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (isObject(source)) {
|
||||
Object.keys(source).forEach(key => {
|
||||
if (isObject(destination[key]) && isObject(source[key])) {
|
||||
mixin(destination[key], source[key], overwrite, level + 1);
|
||||
} else {
|
||||
if (key in destination) {
|
||||
if (overwrite) {
|
||||
if (level === 0 && key === 'type') {
|
||||
// don't merge the 'type' property
|
||||
} else {
|
||||
destination[key] = source[key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
destination[key] = source[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
// only if not already merged
|
||||
if (this.mergedExtensionDescriptions.indexOf(extensionDescription) < 0) {
|
||||
|
||||
// remember all extensions that have been merged for this debugger
|
||||
this.mergedExtensionDescriptions.push(extensionDescription);
|
||||
|
||||
// merge new debugger contribution into existing contributions (and don't overwrite values in built-in extensions)
|
||||
mixin(this.debuggerContribution, otherDebuggerContribution, extensionDescription.isBuiltin);
|
||||
|
||||
// remember the extension that is considered the "main" debugger contribution
|
||||
if (isDebuggerMainContribution(otherDebuggerContribution)) {
|
||||
this.mainExtensionDescription = extensionDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public createDebugAdapter(session: IDebugSession): Promise<IDebugAdapter> {
|
||||
return this.configurationManager.activateDebuggers('onDebugAdapterProtocolTracker', this.type).then(_ => {
|
||||
const da = this.configurationManager.createDebugAdapter(session);
|
||||
if (da) {
|
||||
return Promise.resolve(da);
|
||||
}
|
||||
throw new Error(nls.localize('cannot.find.da', "Cannot find debug adapter for type '{0}'.", this.type));
|
||||
});
|
||||
}
|
||||
|
||||
substituteVariables(folder: IWorkspaceFolder | undefined, config: IConfig): Promise<IConfig> {
|
||||
return this.configurationManager.substituteVariables(this.type, folder, config).then(config => {
|
||||
return this.configurationResolverService.resolveWithInteractionReplace(folder, config, 'launch', this.variables);
|
||||
});
|
||||
}
|
||||
|
||||
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<number | undefined> {
|
||||
const config = this.configurationService.getValue<ITerminalSettings>('terminal');
|
||||
return this.configurationManager.runInTerminal(this.type, args, config);
|
||||
}
|
||||
|
||||
get label(): string {
|
||||
return this.debuggerContribution.label || this.debuggerContribution.type;
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this.debuggerContribution.type;
|
||||
}
|
||||
|
||||
get variables(): { [key: string]: string } | undefined {
|
||||
return this.debuggerContribution.variables;
|
||||
}
|
||||
|
||||
get configurationSnippets(): IJSONSchemaSnippet[] | undefined {
|
||||
return this.debuggerContribution.configurationSnippets;
|
||||
}
|
||||
|
||||
get languages(): string[] | undefined {
|
||||
return this.debuggerContribution.languages;
|
||||
}
|
||||
|
||||
hasInitialConfiguration(): boolean {
|
||||
return !!this.debuggerContribution.initialConfigurations;
|
||||
}
|
||||
|
||||
hasConfigurationProvider(): boolean {
|
||||
return this.configurationManager.hasDebugConfigurationProvider(this.type);
|
||||
}
|
||||
|
||||
getInitialConfigurationContent(initialConfigs?: IConfig[]): Promise<string> {
|
||||
// at this point we got some configs from the package.json and/or from registered DebugConfigurationProviders
|
||||
let initialConfigurations = this.debuggerContribution.initialConfigurations || [];
|
||||
if (initialConfigs) {
|
||||
initialConfigurations = initialConfigurations.concat(initialConfigs);
|
||||
}
|
||||
|
||||
const eol = this.resourcePropertiesService.getEOL(URI.from({ scheme: Schemas.untitled, path: '1' })) === '\r\n' ? '\r\n' : '\n';
|
||||
const configs = JSON.stringify(initialConfigurations, null, '\t').split('\n').map(line => '\t' + line).join(eol).trim();
|
||||
const comment1 = nls.localize('launch.config.comment1', "Use IntelliSense to learn about possible attributes.");
|
||||
const comment2 = nls.localize('launch.config.comment2', "Hover to view descriptions of existing attributes.");
|
||||
const comment3 = nls.localize('launch.config.comment3', "For more information, visit: {0}", 'https://go.microsoft.com/fwlink/?linkid=830387');
|
||||
|
||||
let content = [
|
||||
'{',
|
||||
`\t// ${comment1}`,
|
||||
`\t// ${comment2}`,
|
||||
`\t// ${comment3}`,
|
||||
`\t"version": "0.2.0",`,
|
||||
`\t"configurations": ${configs}`,
|
||||
'}'
|
||||
].join(eol);
|
||||
|
||||
// fix formatting
|
||||
const editorConfig = this.configurationService.getValue<any>();
|
||||
if (editorConfig.editor && editorConfig.editor.insertSpaces) {
|
||||
content = content.replace(new RegExp('\t', 'g'), strings.repeat(' ', editorConfig.editor.tabSize));
|
||||
}
|
||||
|
||||
return Promise.resolve(content);
|
||||
}
|
||||
|
||||
public getMainExtensionDescriptor(): IExtensionDescription {
|
||||
return this.mainExtensionDescription || this.mergedExtensionDescriptions[0];
|
||||
}
|
||||
|
||||
@memoize
|
||||
getCustomTelemetryService(): Promise<TelemetryService | undefined> {
|
||||
|
||||
const aiKey = this.debuggerContribution.aiKey;
|
||||
|
||||
if (!aiKey) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return this.telemetryService.getTelemetryInfo().then(info => {
|
||||
const telemetryInfo: { [key: string]: string } = Object.create(null);
|
||||
telemetryInfo['common.vscodemachineid'] = info.machineId;
|
||||
telemetryInfo['common.vscodesessionid'] = info.sessionId;
|
||||
return telemetryInfo;
|
||||
}).then(data => {
|
||||
const args = [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey];
|
||||
return this.debugHelperService.createTelemetryService(this.configurationService, args);
|
||||
});
|
||||
}
|
||||
|
||||
getSchemaAttributes(): IJSONSchema[] | null {
|
||||
|
||||
if (!this.debuggerContribution.configurationAttributes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// fill in the default configuration attributes shared by all adapters.
|
||||
const taskSchema = TaskDefinitionRegistry.getJsonSchema();
|
||||
return Object.keys(this.debuggerContribution.configurationAttributes).map(request => {
|
||||
const attributes: IJSONSchema = this.debuggerContribution.configurationAttributes[request];
|
||||
const defaultRequired = ['name', 'type', 'request'];
|
||||
attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired;
|
||||
attributes.additionalProperties = false;
|
||||
attributes.type = 'object';
|
||||
if (!attributes.properties) {
|
||||
attributes.properties = {};
|
||||
}
|
||||
const properties = attributes.properties;
|
||||
properties['type'] = {
|
||||
enum: [this.type],
|
||||
description: nls.localize('debugType', "Type of configuration."),
|
||||
pattern: '^(?!node2)',
|
||||
errorMessage: nls.localize('debugTypeNotRecognised', "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled."),
|
||||
patternErrorMessage: nls.localize('node2NotSupported', "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".")
|
||||
};
|
||||
properties['name'] = {
|
||||
type: 'string',
|
||||
description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."),
|
||||
default: 'Launch'
|
||||
};
|
||||
properties['request'] = {
|
||||
enum: [request],
|
||||
description: nls.localize('debugRequest', "Request type of configuration. Can be \"launch\" or \"attach\"."),
|
||||
};
|
||||
properties['debugServer'] = {
|
||||
type: 'number',
|
||||
description: nls.localize('debugServer', "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode"),
|
||||
default: 4711
|
||||
};
|
||||
properties['preLaunchTask'] = {
|
||||
anyOf: [taskSchema, {
|
||||
type: ['string', 'null'],
|
||||
}],
|
||||
default: '',
|
||||
description: nls.localize('debugPrelaunchTask', "Task to run before debug session starts.")
|
||||
};
|
||||
properties['postDebugTask'] = {
|
||||
anyOf: [taskSchema, {
|
||||
type: ['string', 'null'],
|
||||
}],
|
||||
default: '',
|
||||
description: nls.localize('debugPostDebugTask', "Task to run after debug session ends.")
|
||||
};
|
||||
properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA;
|
||||
// Clear out windows, linux and osx fields to not have cycles inside the properties object
|
||||
delete properties['windows'];
|
||||
delete properties['osx'];
|
||||
delete properties['linux'];
|
||||
|
||||
const osProperties = objects.deepClone(properties);
|
||||
properties['windows'] = {
|
||||
type: 'object',
|
||||
description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."),
|
||||
properties: osProperties
|
||||
};
|
||||
properties['osx'] = {
|
||||
type: 'object',
|
||||
description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."),
|
||||
properties: osProperties
|
||||
};
|
||||
properties['linux'] = {
|
||||
type: 'object',
|
||||
description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."),
|
||||
properties: osProperties
|
||||
};
|
||||
Object.keys(properties).forEach(name => {
|
||||
// Use schema allOf property to get independent error reporting #21113
|
||||
ConfigurationResolverUtils.applyDeprecatedVariableMessage(properties[name]);
|
||||
});
|
||||
return attributes;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user