From 84ce1317819a05f87e7d57cd27dbbc910b063383 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2020 11:52:31 +0100 Subject: [PATCH 1/3] Emoji characters in col 40 of an empty file causes crash (fix #111235) --- .../untitled/common/untitledTextEditorModel.ts | 10 +++++++--- .../test/browser/untitledTextEditor.test.ts | 14 +++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts index 92efe2cac0c..630443962d1 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts @@ -22,6 +22,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { getCharContainingOffset } from 'vs/base/common/strings'; export interface IUntitledTextEditorModel extends ITextEditorModel, IModeSupport, IEncodingSupport, IWorkingCopy { @@ -362,15 +363,18 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IUnt let modelFirstWordsCandidate: string | undefined = undefined; - const firstLineText = textEditorModel + let firstLineText = textEditorModel .getValueInRange({ startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: UntitledTextEditorModel.FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH + 1 // first cap at FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH }) - .trim().replace(/\s+/g, ' ') // normalize whitespaces - .substr(0, UntitledTextEditorModel.FIRST_LINE_NAME_MAX_LENGTH); // finally cap at FIRST_LINE_NAME_MAX_LENGTH + .trim().replace(/\s+/g, ' '); // normalize whitespaces + firstLineText = firstLineText.substr(0, getCharContainingOffset( // finally cap at FIRST_LINE_NAME_MAX_LENGTH (grapheme aware #111235) + firstLineText, + UntitledTextEditorModel.FIRST_LINE_NAME_MAX_LENGTH)[0] + ); if (firstLineText && ensureValidWordDefinition().exec(firstLineText)) { modelFirstWordsCandidate = firstLineText; diff --git a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts index 6e0820a85d7..2048b160bf7 100644 --- a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts +++ b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts @@ -446,10 +446,18 @@ suite('Untitled text editors', () => { assert.equal(input.getName(), '([]}hello'); assert.equal(model.name, '([]}hello'); - assert.equal(counter, 4); + model.textEditorModel.setValue('12345678901234567890123456789012345678901234567890'); // trimmed at 40chars max + assert.equal(input.getName(), '1234567890123456789012345678901234567890'); + assert.equal(model.name, '1234567890123456789012345678901234567890'); + + model.textEditorModel.setValue('123456789012345678901234567890123456789🌞'); // do not break grapehems (#111235) + assert.equal(input.getName(), '123456789012345678901234567890123456789'); + assert.equal(model.name, '123456789012345678901234567890123456789'); + + assert.equal(counter, 6); model.textEditorModel.setValue('Hello\nWorld'); - assert.equal(counter, 5); + assert.equal(counter, 7); function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation { let range = new Range( @@ -468,7 +476,7 @@ suite('Untitled text editors', () => { } model.textEditorModel.applyEdits([createSingleEditOp('hello', 2, 2)]); - assert.equal(counter, 5); // change was not on first line + assert.equal(counter, 7); // change was not on first line input.dispose(); model.dispose(); From 3ceea1784692dc6cb859c7c03883e938f4a97d4d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2020 11:53:09 +0100 Subject: [PATCH 2/3] npm: use project dir when using npm --- .../npm/src/features/bowerJSONContribution.ts | 12 ++++---- .../npm/src/features/jsonContributions.ts | 28 +++++++++---------- .../src/features/packageJSONContribution.ts | 28 ++++++++++--------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/extensions/npm/src/features/bowerJSONContribution.ts b/extensions/npm/src/features/bowerJSONContribution.ts index c3a827fd1e1..4fb0f0633b4 100644 --- a/extensions/npm/src/features/bowerJSONContribution.ts +++ b/extensions/npm/src/features/bowerJSONContribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MarkdownString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace } from 'vscode'; +import { MarkdownString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, Uri } from 'vscode'; import { IJSONContribution, ISuggestionsCollector } from './jsonContributions'; import { XHRRequest } from 'request-light'; import { Location } from 'jsonc-parser'; @@ -37,7 +37,7 @@ export class BowerJSONContribution implements IJSONContribution { return !!workspace.getConfiguration('npm').get('fetchOnlinePackageInfo'); } - public collectDefaultSuggestions(_resource: string, collector: ISuggestionsCollector): Thenable { + public collectDefaultSuggestions(_resource: Uri, collector: ISuggestionsCollector): Thenable { const defaultValue = { 'name': '${1:name}', 'description': '${2:description}', @@ -53,7 +53,7 @@ export class BowerJSONContribution implements IJSONContribution { return Promise.resolve(null); } - public collectPropertySuggestions(_resource: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable | null { + public collectPropertySuggestions(_resource: Uri, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable | null { if (!this.isEnabled()) { return null; } @@ -125,7 +125,7 @@ export class BowerJSONContribution implements IJSONContribution { return null; } - public collectValueSuggestions(_resource: string, location: Location, collector: ISuggestionsCollector): Promise | null { + public collectValueSuggestions(_resource: Uri, location: Location, collector: ISuggestionsCollector): Promise | null { if (!this.isEnabled()) { return null; } @@ -141,7 +141,7 @@ export class BowerJSONContribution implements IJSONContribution { return null; } - public resolveSuggestion(item: CompletionItem): Thenable | null { + public resolveSuggestion(_resource: Uri | undefined, item: CompletionItem): Thenable | null { if (item.kind === CompletionItemKind.Property && item.documentation === '') { return this.getInfo(item.label).then(documentation => { if (documentation) { @@ -182,7 +182,7 @@ export class BowerJSONContribution implements IJSONContribution { }); } - public getInfoContribution(_resource: string, location: Location): Thenable | null { + public getInfoContribution(_resource: Uri, location: Location): Thenable | null { if (!this.isEnabled()) { return null; } diff --git a/extensions/npm/src/features/jsonContributions.ts b/extensions/npm/src/features/jsonContributions.ts index 071d57b3348..3954c235168 100644 --- a/extensions/npm/src/features/jsonContributions.ts +++ b/extensions/npm/src/features/jsonContributions.ts @@ -4,14 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { Location, getLocation, createScanner, SyntaxKind, ScanError, JSONScanner } from 'jsonc-parser'; -import { basename } from 'path'; import { BowerJSONContribution } from './bowerJSONContribution'; import { PackageJSONContribution } from './packageJSONContribution'; import { XHRRequest } from 'request-light'; import { CompletionItem, CompletionItemProvider, CompletionList, TextDocument, Position, Hover, HoverProvider, - CancellationToken, Range, MarkedString, DocumentSelector, languages, Disposable + CancellationToken, Range, MarkedString, DocumentSelector, languages, Disposable, Uri } from 'vscode'; export interface ISuggestionsCollector { @@ -23,11 +22,11 @@ export interface ISuggestionsCollector { export interface IJSONContribution { getDocumentSelector(): DocumentSelector; - getInfoContribution(fileName: string, location: Location): Thenable | null; - collectPropertySuggestions(fileName: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable | null; - collectValueSuggestions(fileName: string, location: Location, result: ISuggestionsCollector): Thenable | null; - collectDefaultSuggestions(fileName: string, result: ISuggestionsCollector): Thenable; - resolveSuggestion?(item: CompletionItem): Thenable | null; + getInfoContribution(resourceUri: Uri, location: Location): Thenable | null; + collectPropertySuggestions(resourceUri: Uri, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable | null; + collectValueSuggestions(resourceUri: Uri, location: Location, result: ISuggestionsCollector): Thenable | null; + collectDefaultSuggestions(resourceUri: Uri, result: ISuggestionsCollector): Thenable; + resolveSuggestion?(resourceUri: Uri | undefined, item: CompletionItem): Thenable | null; } export function addJSONProviders(xhr: XHRRequest, canRunNPM: boolean): Disposable { @@ -47,7 +46,6 @@ export class JSONHoverProvider implements HoverProvider { } public provideHover(document: TextDocument, position: Position, _token: CancellationToken): Thenable | null { - const fileName = basename(document.fileName); const offset = document.offsetAt(position); const location = getLocation(document.getText(), offset); if (!location.previousNode) { @@ -55,7 +53,7 @@ export class JSONHoverProvider implements HoverProvider { } const node = location.previousNode; if (node && node.offset <= offset && offset <= node.offset + node.length) { - const promise = this.jsonContribution.getInfoContribution(fileName, location); + const promise = this.jsonContribution.getInfoContribution(document.uri, location); if (promise) { return promise.then(htmlContent => { const range = new Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length)); @@ -73,12 +71,14 @@ export class JSONHoverProvider implements HoverProvider { export class JSONCompletionItemProvider implements CompletionItemProvider { + private lastResource: Uri | undefined; + constructor(private jsonContribution: IJSONContribution) { } public resolveCompletionItem(item: CompletionItem, _token: CancellationToken): Thenable { if (this.jsonContribution.resolveSuggestion) { - const resolver = this.jsonContribution.resolveSuggestion(item); + const resolver = this.jsonContribution.resolveSuggestion(this.lastResource, item); if (resolver) { return resolver; } @@ -87,8 +87,8 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { } public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): Thenable | null { + this.lastResource = document.uri; - const fileName = basename(document.fileName); const currentWord = this.getCurrentWord(document, position); let overwriteRange: Range; @@ -126,12 +126,12 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { const scanner = createScanner(document.getText(), true); const addValue = !location.previousNode || !this.hasColonAfter(scanner, location.previousNode.offset + location.previousNode.length); const isLast = this.isLast(scanner, document.offsetAt(position)); - collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector); + collectPromise = this.jsonContribution.collectPropertySuggestions(document.uri, location, currentWord, addValue, isLast, collector); } else { if (location.path.length === 0) { - collectPromise = this.jsonContribution.collectDefaultSuggestions(fileName, collector); + collectPromise = this.jsonContribution.collectDefaultSuggestions(document.uri, collector); } else { - collectPromise = this.jsonContribution.collectValueSuggestions(fileName, location, collector); + collectPromise = this.jsonContribution.collectValueSuggestions(document.uri, location, collector); } } if (collectPromise) { diff --git a/extensions/npm/src/features/packageJSONContribution.ts b/extensions/npm/src/features/packageJSONContribution.ts index 7fc5475abcc..3249cb7655a 100644 --- a/extensions/npm/src/features/packageJSONContribution.ts +++ b/extensions/npm/src/features/packageJSONContribution.ts @@ -3,13 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MarkedString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, MarkdownString } from 'vscode'; +import { MarkedString, CompletionItemKind, CompletionItem, DocumentSelector, SnippetString, workspace, MarkdownString, Uri } from 'vscode'; import { IJSONContribution, ISuggestionsCollector } from './jsonContributions'; import { XHRRequest } from 'request-light'; import { Location } from 'jsonc-parser'; import * as cp from 'child_process'; import * as nls from 'vscode-nls'; +import { dirname } from 'path'; const localize = nls.loadMessageBundle(); const LIMIT = 40; @@ -35,7 +36,7 @@ export class PackageJSONContribution implements IJSONContribution { public constructor(private xhr: XHRRequest, private canRunNPM: boolean) { } - public collectDefaultSuggestions(_fileName: string, result: ISuggestionsCollector): Thenable { + public collectDefaultSuggestions(_resource: Uri, result: ISuggestionsCollector): Thenable { const defaultValue = { 'name': '${1:name}', 'description': '${2:description}', @@ -60,7 +61,7 @@ export class PackageJSONContribution implements IJSONContribution { } public collectPropertySuggestions( - _resource: string, + _resource: Uri, location: Location, currentWord: string, addValue: boolean, @@ -183,7 +184,7 @@ export class PackageJSONContribution implements IJSONContribution { return Promise.resolve(null); } - public async collectValueSuggestions(_fileName: string, location: Location, result: ISuggestionsCollector): Promise { + public async collectValueSuggestions(resource: Uri, location: Location, result: ISuggestionsCollector): Promise { if (!this.isEnabled()) { return null; } @@ -191,7 +192,7 @@ export class PackageJSONContribution implements IJSONContribution { if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const currentKey = location.path[location.path.length - 1]; if (typeof currentKey === 'string') { - const info = await this.fetchPackageInfo(currentKey); + const info = await this.fetchPackageInfo(currentKey, resource); if (info && info.version) { let name = JSON.stringify(info.version); @@ -236,9 +237,9 @@ export class PackageJSONContribution implements IJSONContribution { return str; } - public resolveSuggestion(item: CompletionItem): Thenable | null { + public resolveSuggestion(resource: Uri | undefined, item: CompletionItem): Thenable | null { if (item.kind === CompletionItemKind.Property && !item.documentation) { - return this.fetchPackageInfo(item.label).then(info => { + return this.fetchPackageInfo(item.label, resource).then(info => { if (info) { item.documentation = this.getDocumentation(info.description, info.version, info.homepage); return item; @@ -266,13 +267,13 @@ export class PackageJSONContribution implements IJSONContribution { return false; } - private async fetchPackageInfo(pack: string): Promise { + private async fetchPackageInfo(pack: string, resource: Uri | undefined): Promise { if (!this.isValidNPMName(pack)) { return undefined; // avoid unnecessary lookups } let info: ViewPackageInfo | undefined; if (this.canRunNPM) { - info = await this.npmView(pack); + info = await this.npmView(pack, resource); } if (!info && this.onlineEnabled()) { info = await this.npmjsView(pack); @@ -280,10 +281,11 @@ export class PackageJSONContribution implements IJSONContribution { return info; } - private npmView(pack: string): Promise { + private npmView(pack: string, resource: Uri | undefined): Promise { return new Promise((resolve, _reject) => { const args = ['view', '--json', pack, 'description', 'dist-tags.latest', 'homepage', 'version']; - cp.execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, (error, stdout) => { + let cwd = resource && resource.scheme === 'file' ? dirname(resource.fsPath) : undefined; + cp.execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, { cwd }, (error, stdout) => { if (!error) { try { const content = JSON.parse(stdout); @@ -325,14 +327,14 @@ export class PackageJSONContribution implements IJSONContribution { return undefined; } - public getInfoContribution(_fileName: string, location: Location): Thenable | null { + public getInfoContribution(resource: Uri, location: Location): Thenable | null { if (!this.isEnabled()) { return null; } if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) { const pack = location.path[location.path.length - 1]; if (typeof pack === 'string') { - return this.fetchPackageInfo(pack).then(info => { + return this.fetchPackageInfo(pack, resource).then(info => { if (info) { return [this.getDocumentation(info.description, info.version, info.homepage)]; } From a15493cf905ee271761646ea81cdf59e6537ca97 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2020 11:51:06 +0100 Subject: [PATCH 3/3] Extract `DebugExtensionHostAction` to its own file --- .../debugExtensionHostAction.ts | 55 +++++++++++++++++++ .../extensions.contribution.ts | 3 +- .../runtimeExtensionsEditor.ts | 47 ---------------- 3 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts diff --git a/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts b/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts new file mode 100644 index 00000000000..bd3ea4886c1 --- /dev/null +++ b/src/vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { IProductService } from 'vs/platform/product/common/productService'; +import { Action } from 'vs/base/common/actions'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; +import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { randomPort } from 'vs/base/node/ports'; + +export class DebugExtensionHostAction extends Action { + static readonly ID = 'workbench.extensions.action.debugExtensionHost'; + static readonly LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); + static readonly CSS_CLASS = 'debug-extension-host'; + + constructor( + @IDebugService private readonly _debugService: IDebugService, + @INativeHostService private readonly _nativeHostService: INativeHostService, + @IDialogService private readonly _dialogService: IDialogService, + @IExtensionService private readonly _extensionService: IExtensionService, + @IProductService private readonly productService: IProductService + ) { + super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS); + } + + async run(): Promise { + + const inspectPort = await this._extensionService.getInspectPort(false); + if (!inspectPort) { + const res = await this._dialogService.confirm({ + type: 'info', + message: nls.localize('restart1', "Profile Extensions"), + detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", this.productService.nameLong), + primaryButton: nls.localize('restart3', "&&Restart"), + secondaryButton: nls.localize('cancel', "&&Cancel") + }); + if (res.confirmed) { + await this._nativeHostService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] }); + } + + return; + } + + return this._debugService.startDebugging(undefined, { + type: 'node', + name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), + request: 'attach', + port: inspectPort + }); + } +} diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index bf55d0c1c1e..4af05bb491b 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -14,7 +14,8 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, DebugExtensionHostAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostProfileService, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, SaveExtensionHostProfileAction, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; +import { DebugExtensionHostAction } from 'vs/workbench/contrib/extensions/electron-browser/debugExtensionHostAction'; import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 7061df39d4b..18c99c8c187 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -5,7 +5,6 @@ import 'vs/css!./media/runtimeExtensionsEditor'; import * as nls from 'vs/nls'; -import { IProductService } from 'vs/platform/product/common/productService'; import { Action, IAction, Separator } from 'vs/base/common/actions'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -28,9 +27,6 @@ import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; -import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; -import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { randomPort } from 'vs/base/node/ports'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ILabelService } from 'vs/platform/label/common/label'; @@ -504,49 +500,6 @@ export class ShowRuntimeExtensionsAction extends Action { } } - -export class DebugExtensionHostAction extends Action { - static readonly ID = 'workbench.extensions.action.debugExtensionHost'; - static readonly LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host"); - static readonly CSS_CLASS = 'debug-extension-host'; - - constructor( - @IDebugService private readonly _debugService: IDebugService, - @INativeHostService private readonly _nativeHostService: INativeHostService, - @IDialogService private readonly _dialogService: IDialogService, - @IExtensionService private readonly _extensionService: IExtensionService, - @IProductService private readonly productService: IProductService - ) { - super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS); - } - - async run(): Promise { - - const inspectPort = await this._extensionService.getInspectPort(false); - if (!inspectPort) { - const res = await this._dialogService.confirm({ - type: 'info', - message: nls.localize('restart1', "Profile Extensions"), - detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", this.productService.nameLong), - primaryButton: nls.localize('restart3', "&&Restart"), - secondaryButton: nls.localize('cancel', "&&Cancel") - }); - if (res.confirmed) { - await this._nativeHostService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] }); - } - - return; - } - - return this._debugService.startDebugging(undefined, { - type: 'node', - name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), - request: 'attach', - port: inspectPort - }); - } -} - export class StartExtensionHostProfileAction extends Action { static readonly ID = 'workbench.extensions.action.extensionHostProfile'; static readonly LABEL = nls.localize('extensionHostProfileStart', "Start Extension Host Profile");