From 73db88ffc1c3bc71a57e372c1388621bf747a866 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Tue, 14 Aug 2018 09:28:29 -0700 Subject: [PATCH 01/44] @import and url() link. Fix Microsoft/vscode#29899 --- .../server/src/cssServerMain.ts | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index 8a822ce8b64..f303eb3b1b0 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -86,6 +86,9 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { referencesProvider: true, definitionProvider: true, documentHighlightProvider: true, + documentLinkProvider: { + resolveProvider: false + }, codeActionProvider: true, renameProvider: true, colorProvider: {}, @@ -227,29 +230,42 @@ connection.onDocumentSymbol((documentSymbolParams, token) => { }, [], `Error while computing document symbols for ${documentSymbolParams.textDocument.uri}`, token); }); -connection.onDefinition((documentSymbolParams, token) => { +connection.onDefinition((documentDefinitionParams, token) => { return runSafe(() => { - const document = documents.get(documentSymbolParams.textDocument.uri); + const document = documents.get(documentDefinitionParams.textDocument.uri); if (document) { const stylesheet = stylesheets.get(document); - return getLanguageService(document).findDefinition(document, documentSymbolParams.position, stylesheet); + return getLanguageService(document).findDefinition(document, documentDefinitionParams.position, stylesheet); } return null; - }, null, `Error while computing definitions for ${documentSymbolParams.textDocument.uri}`, token); + }, null, `Error while computing definitions for ${documentDefinitionParams.textDocument.uri}`, token); }); -connection.onDocumentHighlight((documentSymbolParams, token) => { +connection.onDocumentHighlight((documentHighlightParams, token) => { return runSafe(() => { - const document = documents.get(documentSymbolParams.textDocument.uri); + const document = documents.get(documentHighlightParams.textDocument.uri); if (document) { const stylesheet = stylesheets.get(document); - return getLanguageService(document).findDocumentHighlights(document, documentSymbolParams.position, stylesheet); + return getLanguageService(document).findDocumentHighlights(document, documentHighlightParams.position, stylesheet); } return []; - }, [], `Error while computing document highlights for ${documentSymbolParams.textDocument.uri}`, token); + }, [], `Error while computing document highlights for ${documentHighlightParams.textDocument.uri}`, token); }); + +connection.onDocumentLinks((documentLinkParams, token) => { + return runSafe(() => { + const document = documents.get(documentLinkParams.textDocument.uri); + if (document) { + const stylesheet = stylesheets.get(document); + return getLanguageService(document).findDocumentLinks(document, stylesheet); + } + return []; + }, [], `Error while computing document links for ${documentLinkParams.textDocument.uri}`, token); +}); + + connection.onReferences((referenceParams, token) => { return runSafe(() => { const document = documents.get(referenceParams.textDocument.uri); From 90743215aa2faea9ab9c94c8b328ef3d8c7f8c8b Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 16 Aug 2018 16:01:28 -0700 Subject: [PATCH 02/44] DocumentContext to remove `url` dependency from service --- .../server/src/cssServerMain.ts | 9 +++-- .../server/src/utils/documentContext.ts | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 extensions/css-language-features/server/src/utils/documentContext.ts diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index f303eb3b1b0..853f6690473 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -7,14 +7,14 @@ import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, ServerCapabilities, ConfigurationRequest, WorkspaceFolder } from 'vscode-languageserver'; - +import URI from 'vscode-uri'; import { TextDocument, CompletionList } from 'vscode-languageserver-types'; import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet } from 'vscode-css-languageservice'; import { getLanguageModelCache } from './languageModelCache'; -import { formatError, runSafe } from './utils/runner'; -import URI from 'vscode-uri'; import { getPathCompletionParticipant } from './pathCompletion'; +import { formatError, runSafe } from './utils/runner'; +import { getDocumentContext } from './utils/documentContext'; export interface Settings { css: LanguageSettings; @@ -258,8 +258,9 @@ connection.onDocumentLinks((documentLinkParams, token) => { return runSafe(() => { const document = documents.get(documentLinkParams.textDocument.uri); if (document) { + const documentContext = getDocumentContext(document.uri, workspaceFolders); const stylesheet = stylesheets.get(document); - return getLanguageService(document).findDocumentLinks(document, stylesheet); + return getLanguageService(document).findDocumentLinks(document, stylesheet, documentContext); } return []; }, [], `Error while computing document links for ${documentLinkParams.textDocument.uri}`, token); diff --git a/extensions/css-language-features/server/src/utils/documentContext.ts b/extensions/css-language-features/server/src/utils/documentContext.ts new file mode 100644 index 00000000000..b37993b7655 --- /dev/null +++ b/extensions/css-language-features/server/src/utils/documentContext.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { DocumentContext } from 'vscode-css-languageservice'; +import { endsWith, startsWith } from '../utils/strings'; +import * as url from 'url'; +import { WorkspaceFolder } from 'vscode-languageserver'; + +export function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext { + function getRootFolder(): string | undefined { + for (let folder of workspaceFolders) { + let folderURI = folder.uri; + if (!endsWith(folderURI, '/')) { + folderURI = folderURI + '/'; + } + if (startsWith(documentUri, folderURI)) { + return folderURI; + } + } + return void 0; + } + + return { + resolveReference: (ref, base = documentUri) => { + if (ref[0] === '/') { // resolve absolute path against the current workspace folder + if (startsWith(base, 'file://')) { + let folderUri = getRootFolder(); + if (folderUri) { + return folderUri + ref.substr(1); + } + } + } + return url.resolve(base, ref); + }, + }; +} + From 73ca0345bc091212e254821aa86156a2f0220743 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Mon, 20 Aug 2018 01:06:23 -0700 Subject: [PATCH 03/44] Update css-languageservice --- extensions/css-language-features/server/package.json | 2 +- extensions/css-language-features/server/yarn.lock | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 98a8a370800..6e85706a2f1 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -8,7 +8,7 @@ "node": "*" }, "dependencies": { - "vscode-css-languageservice": "^3.0.10-next.2", + "vscode-css-languageservice": "^3.0.10-next.3", "vscode-languageserver": "^4.4.0" }, "devDependencies": { diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 61e83d9a85d..c2ae2ced51a 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -194,11 +194,11 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^3.0.10-next.2: - version "3.0.10-next.2" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-3.0.10-next.2.tgz#b703af89be433507836178efd7f88bb0669fc4e8" +vscode-css-languageservice@^3.0.10-next.3: + version "3.0.10-next.3" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-3.0.10-next.3.tgz#d663f03b8a9bf11222bd2cd39e9aa05e1a58c58d" dependencies: - vscode-languageserver-types "^3.10.0" + vscode-languageserver-types "^3.10.1" vscode-nls "^3.2.4" vscode-jsonrpc@^3.6.2: @@ -216,6 +216,10 @@ vscode-languageserver-types@^3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.10.0.tgz#944e5308f3b36a3f372c766f1a344e903ec9c389" +vscode-languageserver-types@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.10.1.tgz#d5d5f44f688a3b2aa9857dc53cb9cacca73fe35a" + vscode-languageserver@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-4.4.0.tgz#b6e8b37a739ccb629d92f3635f0099d191c856fa" From 6e559261f677793fea424c6eb5cb13d0301ffff1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 10:17:22 +0200 Subject: [PATCH 04/44] adopt new vscode-nls-dev, #56792 --- build/gulpfile.extensions.js | 4 +++- package.json | 4 ++-- yarn.lock | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 57d52b03b06..bedc9a293fb 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -8,6 +8,7 @@ require('events').EventEmitter.defaultMaxListeners = 100; const gulp = require('gulp'); const path = require('path'); +const fs = require('fs'); const tsb = require('gulp-tsb'); const es = require('event-stream'); const filter = require('gulp-filter'); @@ -74,6 +75,7 @@ const tasks = compilations.map(function (tsconfigFile) { tsOptions.base = path.dirname(absolutePath); const compilation = tsb.create(tsOptions, null, null, err => reporter(err.toString())); + const nlsOption = fs.existsSync(path.join(root, 'extension.webpack.config.js')) ? { keepFilenames: true } : undefined; return function () { const input = es.through(); @@ -89,7 +91,7 @@ const tasks = compilations.map(function (tsconfigFile) { .pipe(tsFilter) .pipe(util.loadSourcemaps()) .pipe(compilation()) - .pipe(build ? nlsDev.rewriteLocalizeCalls({ keepFilenames: true }) : es.through()) + .pipe(build ? nlsDev.rewriteLocalizeCalls(nlsOption) : es.through()) .pipe(build ? util.stripSourceMappingURL() : es.through()) .pipe(sourcemaps.write('.', { sourceMappingURL: !build ? null : f => `${baseUrl}/${f.relative}.map`, diff --git a/package.json b/package.json index d0e982ce0b7..5b73450aa47 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "vinyl": "^0.4.5", "vinyl-fs": "^2.4.3", "vsce": "1.33.2", - "vscode-nls-dev": "3.1.0", + "vscode-nls-dev": "3.1.1", "webpack": "^4.16.5", "webpack-cli": "^3.1.0", "webpack-stream": "^5.1.1" @@ -142,4 +142,4 @@ "windows-mutex": "^0.2.0", "windows-process-tree": "0.2.2" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index b56aa332449..e67580f77c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7880,9 +7880,9 @@ vscode-fsevents@0.3.8: dependencies: nan "^2.3.0" -vscode-nls-dev@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.1.0.tgz#afbd6c6291446a9f82cc19b781841ae307fa36c2" +vscode-nls-dev@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.1.1.tgz#e7fa2e8e641b1579b25779acfda0e5f7c28f1fb9" dependencies: clone "^2.1.1" event-stream "^3.3.4" From d8b0484dc878825898819bbc9d55578e5d3816d5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 20 Aug 2018 10:58:26 +0200 Subject: [PATCH 05/44] menu: integrated terminal => terminal --- src/vs/workbench/parts/terminal/common/terminalMenu.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/common/terminalMenu.ts b/src/vs/workbench/parts/terminal/common/terminalMenu.ts index 52498a02f51..0223a9df008 100644 --- a/src/vs/workbench/parts/terminal/common/terminalMenu.ts +++ b/src/vs/workbench/parts/terminal/common/terminalMenu.ts @@ -16,7 +16,7 @@ export function setupTerminalMenu() { group: '4_panels', command: { id: TERMINAL_COMMAND_ID.TOGGLE, - title: nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, "&&Integrated Terminal") + title: nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal") }, order: 3 }); From c0f818e5ae69aa81112bfe69158a66b731bcad69 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 20 Aug 2018 11:53:20 +0200 Subject: [PATCH 06/44] On Switching Files file is not selected in left pane. Fixes #56588 --- src/vs/base/common/resources.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 53357fe29f5..cefcd007927 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -30,7 +30,7 @@ export function basenameOrAuthority(resource: URI): string { * @param base A uri which is "longer" * @param parentCandidate A uri which is "shorter" then `base` */ -export function isEqualOrParent(base: URI, parentCandidate: URI, ignoreCase?: boolean): boolean { +export function isEqualOrParent(base: URI, parentCandidate: URI, ignoreCase = hasToIgnoreCase(base)): boolean { if (base.scheme === parentCandidate.scheme) { if (base.scheme === Schemas.file) { return paths.isEqualOrParent(fsPath(base), fsPath(parentCandidate), ignoreCase); From 78f6a69173c63da3f9fe9654bbb194930da7cd0a Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 17 Aug 2018 10:53:58 +0200 Subject: [PATCH 07/44] move debug session to a seperate file in electron-browser --- .../parts/debug/browser/debugActions.ts | 6 +- src/vs/workbench/parts/debug/common/debug.ts | 6 +- .../parts/debug/common/debugModel.ts | 185 +----------------- .../debug/electron-browser/callStackView.ts | 3 +- .../debug/electron-browser/debugService.ts | 6 +- .../debug/electron-browser/debugSession.ts | 176 +++++++++++++++++ .../debug/test/browser/baseDebugView.test.ts | 5 +- .../debug/test/common/debugViewModel.test.ts | 5 +- .../parts/debug/test/common/mockDebug.ts | 49 ++++- .../debugModel.test.ts | 22 +-- 10 files changed, 257 insertions(+), 206 deletions(-) create mode 100644 src/vs/workbench/parts/debug/electron-browser/debugSession.ts rename src/vs/workbench/parts/debug/test/{node => electron-browser}/debugModel.test.ts (94%) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 04fd4058642..6191db0921c 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -14,7 +14,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { IFileService } from 'vs/platform/files/common/files'; import { IDebugService, State, ISession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID, SessionState } from 'vs/workbench/parts/debug/common/debug'; -import { Variable, Expression, Thread, Breakpoint, Session } from 'vs/workbench/parts/debug/common/debugModel'; +import { Variable, Expression, Thread, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -230,7 +230,7 @@ export class RestartAction extends AbstractDebugAction { } public run(session: ISession): TPromise { - if (!(session instanceof Session)) { + if (!session || !session.getId) { session = this.debugService.getViewModel().focusedSession; } @@ -325,7 +325,7 @@ export class StopAction extends AbstractDebugAction { } public run(session: ISession): TPromise { - if (!(session instanceof Session)) { + if (!session || !session.getId) { session = this.debugService.getViewModel().focusedSession; } diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 6af33b36e60..d527aef5481 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -146,16 +146,20 @@ export enum SessionState { } export interface ISession extends ITreeElement { - getName(includeRoot: boolean): string; readonly configuration: IConfig; readonly raw: IRawSession; readonly state: SessionState; + + getName(includeRoot: boolean): string; getSourceForUri(modelUri: uri): Source; getThread(threadId: number): IThread; getAllThreads(): ReadonlyArray; getSource(raw: DebugProtocol.Source): Source; getLoadedSources(): TPromise; completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise; + clearThreads(removeThreads: boolean, reference?: number): void; + + rawUpdate(data: IRawModelUpdate): void; } export interface IThread extends ITreeElement { diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 3a58268ec72..6b8a4ef7cff 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -16,14 +16,11 @@ import severity from 'vs/base/common/severity'; import { isObject, isString, isUndefinedOrNull } from 'vs/base/common/types'; import { distinct } from 'vs/base/common/arrays'; import { Range, IRange } from 'vs/editor/common/core/range'; -import { ISuggestion } from 'vs/editor/common/modes'; -import { Position } from 'vs/editor/common/core/position'; import { ITreeElement, IExpression, IExpressionContainer, ISession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel, IReplElementSource, - IConfig, IRawSession, IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, SessionState, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint + IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint } from 'vs/workbench/parts/debug/common/debug'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; -import { mixin } from 'vs/base/common/objects'; import { commonSuffixLength } from 'vs/base/common/strings'; import { sep } from 'vs/base/common/paths'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -552,175 +549,6 @@ export class Thread implements IThread { } } -export class Session implements ISession { - - private sources: Map; - private threads: Map; - - constructor(private _configuration: { resolved: IConfig, unresolved: IConfig }, private session: IRawSession & ITreeElement) { - this.threads = new Map(); - this.sources = new Map(); - } - - public get configuration(): IConfig { - return this._configuration.resolved; - } - - public get unresolvedConfiguration(): IConfig { - return this._configuration.unresolved; - } - - public get raw(): IRawSession & ITreeElement { - return this.session; - } - - public set raw(value: IRawSession & ITreeElement) { - this.session = value; - } - - public getName(includeRoot: boolean): string { - return includeRoot && this.raw.root ? `${this.configuration.name} (${resources.basenameOrAuthority(this.raw.root.uri)})` : this.configuration.name; - } - - public get state(): SessionState { - return this.configuration.type === 'attach' ? SessionState.ATTACH : SessionState.LAUNCH; - } - - public getSourceForUri(modelUri: uri): Source { - return this.sources.get(modelUri.toString()); - } - - public getSource(raw: DebugProtocol.Source): Source { - let source = new Source(raw, this.getId()); - if (this.sources.has(source.uri.toString())) { - source = this.sources.get(source.uri.toString()); - source.raw = mixin(source.raw, raw); - if (source.raw && raw) { - // Always take the latest presentation hint from adapter #42139 - source.raw.presentationHint = raw.presentationHint; - } - } else { - this.sources.set(source.uri.toString(), source); - } - - return source; - } - - public getThread(threadId: number): Thread { - return this.threads.get(threadId); - } - - public getAllThreads(): IThread[] { - const result: IThread[] = []; - this.threads.forEach(t => result.push(t)); - return result; - } - - public getLoadedSources(): TPromise { - return this.raw.loadedSources({}).then(response => { - return response.body.sources.map(src => this.getSource(src)); - }, error => { - return []; - }); - } - - public getId(): string { - return this.session.getId(); - } - - public rawUpdate(data: IRawModelUpdate): void { - - if (data.thread && !this.threads.has(data.threadId)) { - // A new thread came in, initialize it. - this.threads.set(data.threadId, new Thread(this, data.thread.name, data.thread.id)); - } else if (data.thread && data.thread.name) { - // Just the thread name got updated #18244 - this.threads.get(data.threadId).name = data.thread.name; - } - - if (data.stoppedDetails) { - // Set the availability of the threads' callstacks depending on - // whether the thread is stopped or not - if (data.stoppedDetails.allThreadsStopped) { - this.threads.forEach(thread => { - thread.stoppedDetails = thread.threadId === data.threadId ? data.stoppedDetails : { reason: undefined }; - thread.stopped = true; - thread.clearCallStack(); - }); - } else if (this.threads.has(data.threadId)) { - // One thread is stopped, only update that thread. - const thread = this.threads.get(data.threadId); - thread.stoppedDetails = data.stoppedDetails; - thread.clearCallStack(); - thread.stopped = true; - } - } - } - - public clearThreads(removeThreads: boolean, reference: number = undefined): void { - if (reference !== undefined && reference !== null) { - if (this.threads.has(reference)) { - const thread = this.threads.get(reference); - thread.clearCallStack(); - thread.stoppedDetails = undefined; - thread.stopped = false; - - if (removeThreads) { - this.threads.delete(reference); - } - } - } else { - this.threads.forEach(thread => { - thread.clearCallStack(); - thread.stoppedDetails = undefined; - thread.stopped = false; - }); - - if (removeThreads) { - this.threads.clear(); - ExpressionContainer.allValues.clear(); - } - } - } - - public completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise { - if (!this.raw.capabilities.supportsCompletionsRequest) { - return TPromise.as([]); - } - - return this.raw.completions({ - frameId, - text, - column: position.column, - line: position.lineNumber - }).then(response => { - const result: ISuggestion[] = []; - if (response && response.body && response.body.targets) { - response.body.targets.forEach(item => { - if (item && item.label) { - result.push({ - label: item.label, - insertText: item.text || item.label, - type: item.type, - filterText: item.start && item.length && text.substr(item.start, item.length).concat(item.label), - overwriteBefore: item.length || overwriteBefore - }); - } - }); - } - - return result; - }, () => []); - } - - setNotAvailable(modelUri: uri) { - const source = this.sources.get(modelUri.toString()); - if (source) { - source.available = false; - } - } -} - export class Enablement implements IEnablement { constructor( public enabled: boolean, @@ -905,7 +733,7 @@ export class ThreadAndSessionIds implements ITreeElement { export class Model implements IModel { - private sessions: Session[]; + private sessions: ISession[]; private toDispose: lifecycle.IDisposable[]; private replElements: IReplElement[]; private schedulers = new Map(); @@ -935,15 +763,12 @@ export class Model implements IModel { return 'root'; } - public getSessions(): Session[] { + public getSessions(): ISession[] { return this.sessions; } - public addSession(configuration: { resolved: IConfig, unresolved: IConfig }, raw: IRawSession & ITreeElement): Session { - const session = new Session(configuration, raw); + public addSession(session: ISession): void { this.sessions.push(session); - - return session; } public removeSession(id: string): void { @@ -1277,7 +1102,7 @@ export class Model implements IModel { } public sourceIsNotAvailable(uri: uri): void { - this.sessions.forEach(p => p.setNotAvailable(uri)); + this.sessions.forEach(p => p.getSourceForUri(uri).available = false); this._onDidChangeCallStack.fire(); } diff --git a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts index 64e48d2f6d9..0298950898c 100644 --- a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import { TreeViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IDebugService, State, IStackFrame, ISession, IThread, CONTEXT_CALLSTACK_ITEM_TYPE } from 'vs/workbench/parts/debug/common/debug'; -import { Thread, StackFrame, ThreadAndSessionIds, Session, Model } from 'vs/workbench/parts/debug/common/debugModel'; +import { Thread, StackFrame, ThreadAndSessionIds, Model } from 'vs/workbench/parts/debug/common/debugModel'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MenuId } from 'vs/platform/actions/common/actions'; @@ -28,6 +28,7 @@ import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet'; import { IUriLabelService } from 'vs/platform/uriLabel/common/uriLabel'; +import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession'; const $ = dom.$; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index a5e2dcee7a0..73c6353846b 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -28,7 +28,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import * as debug from 'vs/workbench/parts/debug/common/debug'; import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession'; -import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, RawObjectReplElement, ExpressionContainer, Session, Thread } from 'vs/workbench/parts/debug/common/debugModel'; +import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, RawObjectReplElement, ExpressionContainer, Thread } from 'vs/workbench/parts/debug/common/debugModel'; import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import * as debugactions from 'vs/workbench/parts/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/parts/debug/electron-browser/debugConfigurationManager'; @@ -55,6 +55,7 @@ import { normalizeDriveLetter } from 'vs/base/common/labels'; import { RunOnceScheduler } from 'vs/base/common/async'; import product from 'vs/platform/node/product'; import { deepClone, equals } from 'vs/base/common/objects'; +import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession'; const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; @@ -895,7 +896,8 @@ export class DebugService implements debug.IDebugService { const raw = this.instantiationService.createInstance(RawDebugSession, sessionId, configuration.resolved.debugServer, dbg, customTelemetryService, root); if (!session) { - session = this.model.addSession(configuration, raw); + session = new Session(configuration, raw); + this.model.addSession(session); this.allSessions.set(session.getId(), session); } else { session.raw = raw; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts new file mode 100644 index 00000000000..75170c00238 --- /dev/null +++ b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts @@ -0,0 +1,176 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import uri from 'vs/base/common/uri'; +import * as resources from 'vs/base/common/resources'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ISuggestion } from 'vs/editor/common/modes'; +import { Position } from 'vs/editor/common/core/position'; +import { ITreeElement, ISession, IConfig, IRawSession, IThread, IRawModelUpdate, SessionState } from 'vs/workbench/parts/debug/common/debug'; +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; +import { mixin } from 'vs/base/common/objects'; +import { Thread, ExpressionContainer } from 'vs/workbench/parts/debug/common/debugModel'; + +export class Session implements ISession { + + private sources: Map; + private threads: Map; + + constructor(private _configuration: { resolved: IConfig, unresolved: IConfig }, private session: IRawSession & ITreeElement) { + this.threads = new Map(); + this.sources = new Map(); + } + + public get configuration(): IConfig { + return this._configuration.resolved; + } + + public get unresolvedConfiguration(): IConfig { + return this._configuration.unresolved; + } + + public get raw(): IRawSession & ITreeElement { + return this.session; + } + + public set raw(value: IRawSession & ITreeElement) { + this.session = value; + } + + public getName(includeRoot: boolean): string { + return includeRoot && this.raw.root ? `${this.configuration.name} (${resources.basenameOrAuthority(this.raw.root.uri)})` : this.configuration.name; + } + + public get state(): SessionState { + return this.configuration.type === 'attach' ? SessionState.ATTACH : SessionState.LAUNCH; + } + + public getSourceForUri(modelUri: uri): Source { + return this.sources.get(modelUri.toString()); + } + + public getSource(raw: DebugProtocol.Source): Source { + let source = new Source(raw, this.getId()); + if (this.sources.has(source.uri.toString())) { + source = this.sources.get(source.uri.toString()); + source.raw = mixin(source.raw, raw); + if (source.raw && raw) { + // Always take the latest presentation hint from adapter #42139 + source.raw.presentationHint = raw.presentationHint; + } + } else { + this.sources.set(source.uri.toString(), source); + } + + return source; + } + + public getThread(threadId: number): Thread { + return this.threads.get(threadId); + } + + public getAllThreads(): IThread[] { + const result: IThread[] = []; + this.threads.forEach(t => result.push(t)); + return result; + } + + public getLoadedSources(): TPromise { + return this.raw.loadedSources({}).then(response => { + return response.body.sources.map(src => this.getSource(src)); + }, error => { + return []; + }); + } + + public getId(): string { + return this.session.getId(); + } + + public rawUpdate(data: IRawModelUpdate): void { + + if (data.thread && !this.threads.has(data.threadId)) { + // A new thread came in, initialize it. + this.threads.set(data.threadId, new Thread(this, data.thread.name, data.thread.id)); + } else if (data.thread && data.thread.name) { + // Just the thread name got updated #18244 + this.threads.get(data.threadId).name = data.thread.name; + } + + if (data.stoppedDetails) { + // Set the availability of the threads' callstacks depending on + // whether the thread is stopped or not + if (data.stoppedDetails.allThreadsStopped) { + this.threads.forEach(thread => { + thread.stoppedDetails = thread.threadId === data.threadId ? data.stoppedDetails : { reason: undefined }; + thread.stopped = true; + thread.clearCallStack(); + }); + } else if (this.threads.has(data.threadId)) { + // One thread is stopped, only update that thread. + const thread = this.threads.get(data.threadId); + thread.stoppedDetails = data.stoppedDetails; + thread.clearCallStack(); + thread.stopped = true; + } + } + } + + public clearThreads(removeThreads: boolean, reference: number = undefined): void { + if (reference !== undefined && reference !== null) { + if (this.threads.has(reference)) { + const thread = this.threads.get(reference); + thread.clearCallStack(); + thread.stoppedDetails = undefined; + thread.stopped = false; + + if (removeThreads) { + this.threads.delete(reference); + } + } + } else { + this.threads.forEach(thread => { + thread.clearCallStack(); + thread.stoppedDetails = undefined; + thread.stopped = false; + }); + + if (removeThreads) { + this.threads.clear(); + ExpressionContainer.allValues.clear(); + } + } + } + + public completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise { + if (!this.raw.capabilities.supportsCompletionsRequest) { + return TPromise.as([]); + } + + return this.raw.completions({ + frameId, + text, + column: position.column, + line: position.lineNumber + }).then(response => { + const result: ISuggestion[] = []; + if (response && response.body && response.body.targets) { + response.body.targets.forEach(item => { + if (item && item.label) { + result.push({ + label: item.label, + insertText: item.text || item.label, + type: item.type, + filterText: item.start && item.length && text.substr(item.start, item.length).concat(item.label), + overwriteBefore: item.length || overwriteBefore + }); + } + }); + } + + return result; + }, () => []); + } +} diff --git a/src/vs/workbench/parts/debug/test/browser/baseDebugView.test.ts b/src/vs/workbench/parts/debug/test/browser/baseDebugView.test.ts index d52a69598b8..837cb46a9b6 100644 --- a/src/vs/workbench/parts/debug/test/browser/baseDebugView.test.ts +++ b/src/vs/workbench/parts/debug/test/browser/baseDebugView.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { replaceWhitespace, renderExpressionValue, renderVariable } from 'vs/workbench/parts/debug/browser/baseDebugView'; import * as dom from 'vs/base/browser/dom'; -import { Expression, Variable, Session, Scope, StackFrame, Thread } from 'vs/workbench/parts/debug/common/debugModel'; +import { Expression, Variable, Scope, StackFrame, Thread } from 'vs/workbench/parts/debug/common/debugModel'; import { MockSession } from 'vs/workbench/parts/debug/test/common/mockDebug'; const $ = dom.$; @@ -52,8 +52,7 @@ suite('Debug - Base Debug View', () => { }); test('render variable', () => { - const rawSession = new MockSession(); - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new MockSession(); const thread = new Thread(session, 'mockthread', 1); const stackFrame = new StackFrame(thread, 1, null, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: undefined, endColumn: undefined }, 0); const scope = new Scope(stackFrame, 1, 'local', 1, false, 10, 10); diff --git a/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts index 733ae781c37..a466b211fe4 100644 --- a/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; -import { StackFrame, Expression, Thread, Session } from 'vs/workbench/parts/debug/common/debugModel'; +import { StackFrame, Expression, Thread } from 'vs/workbench/parts/debug/common/debugModel'; import { MockSession } from 'vs/workbench/parts/debug/test/common/mockDebug'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; @@ -23,8 +23,7 @@ suite('Debug - View Model', () => { test('focused stack frame', () => { assert.equal(model.focusedStackFrame, null); assert.equal(model.focusedThread, null); - const mockSession = new MockSession(); - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, mockSession); + const session = new MockSession(); const thread = new Thread(session, 'myThread', 1); const frame = new StackFrame(thread, 1, null, 'app.js', 'normal', { startColumn: 1, startLineNumber: 1, endColumn: undefined, endLineNumber: undefined }, 0); model.setFocus(frame, thread, session, false); diff --git a/src/vs/workbench/parts/debug/test/common/mockDebug.ts b/src/vs/workbench/parts/debug/test/common/mockDebug.ts index f92a322a3a0..c9914760a19 100644 --- a/src/vs/workbench/parts/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/parts/debug/test/common/mockDebug.ts @@ -7,7 +7,10 @@ import uri from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { ILaunch, IDebugService, State, DebugEvent, ISession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawSession, IBreakpoint, LoadedSourceEvent } from 'vs/workbench/parts/debug/common/debug'; +import { Position } from 'vs/editor/common/core/position'; +import { ILaunch, IDebugService, State, DebugEvent, ISession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawSession, IBreakpoint, LoadedSourceEvent, SessionState, IThread, IRawModelUpdate } from 'vs/workbench/parts/debug/common/debug'; +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; +import { ISuggestion } from 'vs/editor/common/modes'; export class MockDebugService implements IDebugService { public _serviceBrand: any; @@ -114,7 +117,49 @@ export class MockDebugService implements IDebugService { public sourceIsNotAvailable(uri: uri): void { } } -export class MockSession implements IRawSession { +export class MockSession implements ISession { + configuration: IConfig = { type: 'mock', request: 'launch' }; + raw: IRawSession = new MockRawSession(); + state = SessionState.LAUNCH; + + getName(includeRoot: boolean): string { + return 'mockname'; + } + + getSourceForUri(modelUri: uri): Source { + return null; + } + + getThread(threadId: number): IThread { + return null; + } + + getAllThreads(): ReadonlyArray { + return []; + } + + getSource(raw: DebugProtocol.Source): Source { + return undefined; + } + + getLoadedSources(): TPromise { + return TPromise.as([]); + } + + completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise { + return TPromise.as([]); + } + + clearThreads(removeThreads: boolean, reference?: number): void { } + + rawUpdate(data: IRawModelUpdate): void { } + + getId(): string { + return 'mock'; + } +} + +export class MockRawSession implements IRawSession { public readyForBreakpoints = true; public emittedStopped = true; diff --git a/src/vs/workbench/parts/debug/test/node/debugModel.test.ts b/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts similarity index 94% rename from src/vs/workbench/parts/debug/test/node/debugModel.test.ts rename to src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts index e480fb71cb6..3e448f864e7 100644 --- a/src/vs/workbench/parts/debug/test/node/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts @@ -6,18 +6,19 @@ import * as assert from 'assert'; import uri from 'vs/base/common/uri'; import severity from 'vs/base/common/severity'; -import { SimpleReplElement, Model, Session, Expression, RawObjectReplElement, StackFrame, Thread } from 'vs/workbench/parts/debug/common/debugModel'; +import { SimpleReplElement, Model, Expression, RawObjectReplElement, StackFrame, Thread } from 'vs/workbench/parts/debug/common/debugModel'; import * as sinon from 'sinon'; -import { MockSession } from 'vs/workbench/parts/debug/test/common/mockDebug'; +import { MockRawSession } from 'vs/workbench/parts/debug/test/common/mockDebug'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; +import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession'; suite('Debug - Model', () => { let model: Model; - let rawSession: MockSession; + let rawSession: MockRawSession; setup(() => { model = new Model([], true, [], [], []); - rawSession = new MockSession(); + rawSession = new MockRawSession(); }); teardown(() => { @@ -108,8 +109,8 @@ suite('Debug - Model', () => { test('threads simple', () => { const threadId = 1; const threadName = 'firstThread'; - - model.addSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + model.addSession(session); assert.equal(model.getSessions().length, 1); model.rawUpdate({ sessionId: rawSession.getId(), @@ -119,7 +120,6 @@ suite('Debug - Model', () => { name: threadName } }); - const session = model.getSessions().filter(p => p.getId() === rawSession.getId()).pop(); assert.equal(session.getThread(threadId).name, threadName); @@ -140,7 +140,8 @@ suite('Debug - Model', () => { const stoppedReason = 'breakpoint'; // Add the threads - model.addSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + model.addSession(session); model.rawUpdate({ sessionId: rawSession.getId(), threadId: threadId1, @@ -169,7 +170,6 @@ suite('Debug - Model', () => { allThreadsStopped: true }, }); - const session = model.getSessions().filter(p => p.getId() === rawSession.getId()).pop(); const thread1 = session.getThread(threadId1); const thread2 = session.getThread(threadId2); @@ -230,7 +230,8 @@ suite('Debug - Model', () => { const runningThreadId = 2; const runningThreadName = 'runningThread'; const stoppedReason = 'breakpoint'; - model.addSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + model.addSession(session); // Add the threads model.rawUpdate({ sessionId: rawSession.getId(), @@ -260,7 +261,6 @@ suite('Debug - Model', () => { allThreadsStopped: false } }); - const session = model.getSessions().filter(p => p.getId() === rawSession.getId()).pop(); const stoppedThread = session.getThread(stoppedThreadId); const runningThread = session.getThread(runningThreadId); From 758be52acf26b54ec70fa31ee6c4eb4d89835670 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 11:58:07 +0200 Subject: [PATCH 08/44] Reify "DebugSession" fixes #48377 --- .../mainThreadDebugService.ts | 20 +- .../parts/debug/browser/debugActions.ts | 4 +- .../parts/debug/browser/debugEditorActions.ts | 2 +- .../parts/debug/browser/loadedScriptsView.ts | 20 +- src/vs/workbench/parts/debug/common/debug.ts | 47 +- .../debug/electron-browser/debugService.ts | 631 +++++------------- .../debug/electron-browser/debugSession.ts | 322 ++++++++- .../debug/electron-browser/rawDebugSession.ts | 24 +- .../parts/debug/test/common/mockDebug.ts | 60 +- .../test/electron-browser/debugModel.test.ts | 33 +- 10 files changed, 576 insertions(+), 587 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index b98563c70b1..3769f8b0c6b 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -29,14 +29,22 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb private _debugAdapters: Map; private _debugAdaptersHandleCounter = 1; - constructor( extHostContext: IExtHostContext, @IDebugService private debugService: IDebugService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDebugService); this._toDispose = []; - this._toDispose.push(debugService.onDidNewSession(proc => this._proxy.$acceptDebugSessionStarted(proc.getId(), proc.configuration.type, proc.getName(false)))); + this._toDispose.push(debugService.onDidNewSession(session => { + this._proxy.$acceptDebugSessionStarted(session.getId(), session.configuration.type, session.getName(false)); + this._toDispose.push(session.onDidCustomEvent(event => { + if (event && event.sessionId) { + if (process) { + this._proxy.$acceptDebugSessionCustomEvent(event.sessionId, session.configuration.type, session.configuration.name, event); + } + } + })); + })); this._toDispose.push(debugService.onDidEndSession(proc => this._proxy.$acceptDebugSessionTerminated(proc.getId(), proc.configuration.type, proc.getName(false)))); this._toDispose.push(debugService.getViewModel().onDidFocusSession(proc => { if (proc) { @@ -46,14 +54,6 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb } })); - this._toDispose.push(debugService.onDidCustomEvent(event => { - if (event && event.sessionId) { - const process = this.debugService.getModel().getSessions().filter(p => p.getId() === event.sessionId).pop(); - if (process) { - this._proxy.$acceptDebugSessionCustomEvent(event.sessionId, process.configuration.type, process.configuration.name, event); - } - } - })); this._debugAdapters = new Map(); } diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 6191db0921c..1d35bf5ea64 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -12,7 +12,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import * as aria from 'vs/base/browser/ui/aria/aria'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IFileService } from 'vs/platform/files/common/files'; -import { IDebugService, State, ISession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID, SessionState } +import { IDebugService, State, ISession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID } from 'vs/workbench/parts/debug/common/debug'; import { Variable, Expression, Thread, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import { IPartService } from 'vs/workbench/services/part/common/partService'; @@ -226,7 +226,7 @@ export class RestartAction extends AbstractDebugAction { } private setLabel(session: ISession): void { - this.updateLabel(session && session.state === SessionState.ATTACH ? RestartAction.RECONNECT_LABEL : RestartAction.LABEL); + this.updateLabel(session && session.configuration.request === 'attach' ? RestartAction.RECONNECT_LABEL : RestartAction.LABEL); } public run(session: ISession): TPromise { diff --git a/src/vs/workbench/parts/debug/browser/debugEditorActions.ts b/src/vs/workbench/parts/debug/browser/debugEditorActions.ts index d6332e2f2ca..3d00826481d 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorActions.ts @@ -118,7 +118,7 @@ class RunToCursorAction extends EditorAction { } let breakpointToRemove: IBreakpoint; - const oneTimeListener = debugService.getViewModel().focusedSession.raw.onDidEvent(event => { + const oneTimeListener = debugService.getViewModel().focusedSession.onDidCustomEvent(event => { if (event.event === 'stopped' || event.event === 'exit') { if (breakpointToRemove) { debugService.removeBreakpoints(breakpointToRemove.getId()); diff --git a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts index 780b5ebb659..b8bd358a6cf 100644 --- a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts +++ b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts @@ -371,16 +371,18 @@ export class LoadedScriptsView extends TreeViewsViewletPanel { let timeout: number; - this.disposables.push(this.debugService.onDidLoadedSource(event => { - const sessionRoot = root.add(event.session); - sessionRoot.addPath(event.source); + this.disposables.push(this.debugService.onDidNewSession(session => { + this.disposables.push(session.onDidLoadedSource(event => { + const sessionRoot = root.add(session); + sessionRoot.addPath(event.source); - clearTimeout(timeout); - timeout = setTimeout(() => { - if (this.tree) { - this.tree.refresh(root, true); - } - }, 300); + clearTimeout(timeout); + timeout = setTimeout(() => { + if (this.tree) { + this.tree.refresh(root, true); + } + }, 300); + })); })); this.disposables.push(this.debugService.onDidEndSession(session => { diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index d527aef5481..d832d738ecb 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -109,7 +109,6 @@ export interface IExpression extends IReplElement, IExpressionContainer { } export interface IRawSession { - readonly root: IWorkspaceFolder; stackTrace(args: DebugProtocol.StackTraceArguments): TPromise; exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise; scopes(args: DebugProtocol.ScopesArguments): TPromise; @@ -117,11 +116,9 @@ export interface IRawSession { evaluate(args: DebugProtocol.EvaluateArguments): TPromise; readonly capabilities: DebugProtocol.Capabilities; + disconnect(restart?: boolean): TPromise; terminate(restart?: boolean): TPromise; custom(request: string, args: any): TPromise; - onDidEvent: Event; - onDidInitialize: Event; - onDidExitAdapter: Event<{ sessionId: string }>; restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): TPromise; next(args: DebugProtocol.NextArguments): TPromise; @@ -140,15 +137,11 @@ export interface IRawSession { } -export enum SessionState { - ATTACH, - LAUNCH -} - -export interface ISession extends ITreeElement { +export interface ISession extends ITreeElement, IDisposable { readonly configuration: IConfig; readonly raw: IRawSession; - readonly state: SessionState; + readonly state: State; + readonly root: IWorkspaceFolder; getName(includeRoot: boolean): string; getSourceForUri(modelUri: uri): Source; @@ -160,6 +153,18 @@ export interface ISession extends ITreeElement { clearThreads(removeThreads: boolean, reference?: number): void; rawUpdate(data: IRawModelUpdate): void; + + /** + * Allows to register on loaded source events. + */ + onDidLoadedSource: Event; + + /** + * Allows to register on custom DAP events. + */ + onDidCustomEvent: Event; + + onDidExitAdapter: Event; } export interface IThread extends ITreeElement { @@ -581,7 +586,6 @@ export interface DebugEvent extends DebugProtocol.Event { } export interface LoadedSourceEvent { - session: ISession; reason: string; source: Source; } @@ -609,16 +613,6 @@ export interface IDebugService { */ onDidEndSession: Event; - /** - * Allows to register on loaded source events. - */ - onDidLoadedSource: Event; - - /** - * Allows to register on custom DAP events. - */ - onDidCustomEvent: Event; - /** * Gets the current configuration manager. */ @@ -687,7 +681,7 @@ export interface IDebugService { /** * Appends the passed string to the debug repl. */ - logToRepl(value: string, sev?: severity): void; + logToRepl(value: string | IExpression, sev?: severity, source?: IReplElementSource): void; /** * Adds a new watch expression and evaluates it against the debug adapter. @@ -719,7 +713,7 @@ export interface IDebugService { /** * Restarts a session or creates a new one if there is no active session. */ - restartSession(session: ISession): TPromise; + restartSession(session: ISession, restartData?: any): TPromise; /** * Stops the session. If the session does not exist then stops all sessions. @@ -740,6 +734,11 @@ export interface IDebugService { * Gets the current view model. */ getViewModel(): IViewModel; + + /** + * Try to auto focus the top stack frame of the passed thread. + */ + tryToAutoFocusStackFrame(thread: IThread): TPromise; } // Editor interfaces diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 73c6353846b..a360dabf1cc 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as lifecycle from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import * as resources from 'vs/base/common/resources'; -import * as strings from 'vs/base/common/strings'; import { generateUuid } from 'vs/base/common/uuid'; import uri from 'vs/base/common/uri'; -import * as platform from 'vs/base/common/platform'; import { first, distinct } from 'vs/base/common/arrays'; import { isObject, isUndefinedOrNull } from 'vs/base/common/types'; import * as errors from 'vs/base/common/errors'; @@ -26,9 +23,8 @@ import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/file import { IWindowService } from 'vs/platform/windows/common/windows'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import * as debug from 'vs/workbench/parts/debug/common/debug'; import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession'; -import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, RawObjectReplElement, ExpressionContainer, Thread } from 'vs/workbench/parts/debug/common/debugModel'; +import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, RawObjectReplElement } from 'vs/workbench/parts/debug/common/debugModel'; import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import * as debugactions from 'vs/workbench/parts/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/parts/debug/electron-browser/debugConfigurationManager'; @@ -43,7 +39,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost'; +import { EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost'; import { IBroadcastService, IBroadcast } from 'vs/platform/broadcast/electron-browser/broadcastService'; import { IRemoteConsoleLog, parse, getFirstFrame } from 'vs/base/node/console'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; @@ -52,10 +48,11 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IAction, Action } from 'vs/base/common/actions'; import { normalizeDriveLetter } from 'vs/base/common/labels'; -import { RunOnceScheduler } from 'vs/base/common/async'; -import product from 'vs/platform/node/product'; import { deepClone, equals } from 'vs/base/common/objects'; import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession'; +import { equalsIgnoreCase } from 'vs/base/common/strings'; +import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { IDebugService, State, ISession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IModel, IReplElementSource, IEnablement, IBreakpoint, IBreakpointData, IExpression, ICompound, IGlobalConfig, IStackFrame } from 'vs/workbench/parts/debug/common/debug'; const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; @@ -63,29 +60,24 @@ const DEBUG_FUNCTION_BREAKPOINTS_KEY = 'debug.functionbreakpoint'; const DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint'; const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions'; -export class DebugService implements debug.IDebugService { - public _serviceBrand: any; +export class DebugService implements IDebugService { + _serviceBrand: any; - private sessionStates: Map; - private readonly _onDidChangeState: Emitter; - private readonly _onDidNewSession: Emitter; - private readonly _onDidEndSession: Emitter; - private readonly _onDidLoadedSource: Emitter; - private readonly _onDidCustomEvent: Emitter; + private readonly _onDidChangeState: Emitter; + private readonly _onDidNewSession: Emitter; + private readonly _onDidEndSession: Emitter; private model: Model; private viewModel: ViewModel; - private allSessions: Map; private configurationManager: ConfigurationManager; - private toDispose: lifecycle.IDisposable[]; - private toDisposeOnSessionEnd: Map; + private allSessions = new Map(); + private toDispose: IDisposable[]; private debugType: IContextKey; private debugState: IContextKey; private inDebugMode: IContextKey; private breakpointsToSendOnResourceSaved: Set; private firstSessionStart: boolean; private skipRunningTask: boolean; - private previousState: debug.State; - private fetchThreadsSchedulers: Map; + private previousState: State; constructor( @IStorageService private storageService: IStorageService, @@ -110,22 +102,16 @@ export class DebugService implements debug.IDebugService { @IConfigurationService private configurationService: IConfigurationService, ) { this.toDispose = []; - this.toDisposeOnSessionEnd = new Map(); this.breakpointsToSendOnResourceSaved = new Set(); - this._onDidChangeState = new Emitter(); - this._onDidNewSession = new Emitter(); - this._onDidEndSession = new Emitter(); - this._onDidLoadedSource = new Emitter(); - this._onDidCustomEvent = new Emitter(); - this.sessionStates = new Map(); - this.allSessions = new Map(); - this.fetchThreadsSchedulers = new Map(); + this._onDidChangeState = new Emitter(); + this._onDidNewSession = new Emitter(); + this._onDidEndSession = new Emitter(); this.configurationManager = this.instantiationService.createInstance(ConfigurationManager); this.toDispose.push(this.configurationManager); - this.debugType = debug.CONTEXT_DEBUG_TYPE.bindTo(contextKeyService); - this.debugState = debug.CONTEXT_DEBUG_STATE.bindTo(contextKeyService); - this.inDebugMode = debug.CONTEXT_IN_DEBUG_MODE.bindTo(contextKeyService); + this.debugType = CONTEXT_DEBUG_TYPE.bindTo(contextKeyService); + this.debugState = CONTEXT_DEBUG_STATE.bindTo(contextKeyService); + this.inDebugMode = CONTEXT_IN_DEBUG_MODE.bindTo(contextKeyService); this.model = new Model(this.loadBreakpoints(), this.storageService.getBoolean(DEBUG_BREAKPOINTS_ACTIVATED_KEY, StorageScope.WORKSPACE, true), this.loadFunctionBreakpoints(), this.loadExceptionBreakpoints(), this.loadWatchExpressions()); @@ -144,18 +130,17 @@ export class DebugService implements debug.IDebugService { this.toDispose.push(this.viewModel.onDidFocusSession(s => { const id = s ? s.getId() : undefined; this.model.setBreakpointsSessionId(id); + this.onStateChange(); })); } private onBroadcast(broadcast: IBroadcast): void { - // attach: PH is ready to be attached to const session = this.allSessions.get(broadcast.payload.debugId); if (!session) { // Ignore attach events for sessions that never existed (wrong vscode windows) return; } - const raw = session.raw; if (broadcast.channel === EXTENSION_ATTACH_BROADCAST_CHANNEL) { const initialAttach = session.configuration.request === 'launch'; @@ -164,22 +149,20 @@ export class DebugService implements debug.IDebugService { session.configuration.port = broadcast.payload.port; // Do not end process on initial attach (since the request is still 'launch') if (initialAttach) { - const root = raw.root; - lifecycle.dispose(this.toDisposeOnSessionEnd[raw.getId()]); - this.initializeRawSession(root, { resolved: session.configuration, unresolved: session.unresolvedConfiguration }, session.getId(), session).then(session => { - (session.raw).attach(session.configuration); - }); + const dbgr = this.configurationManager.getDebugger(session.configuration.type); + session.initialize(dbgr).then(() => (session.raw).attach(session.configuration)); } else { - const root = raw.root; - raw.disconnect().done(undefined, errors.onUnexpectedError); - this.doCreateSession(root, { resolved: session.configuration, unresolved: session.unresolvedConfiguration }, session.getId()); + if (session.raw) { + session.raw.disconnect().done(undefined, errors.onUnexpectedError); + } + this.doCreateSession(session.root, { resolved: session.configuration, unresolved: session.unresolvedConfiguration }, session.getId()); } return; } if (broadcast.channel === EXTENSION_TERMINATE_BROADCAST_CHANNEL) { - raw.terminate().done(undefined, errors.onUnexpectedError); + session.raw.terminate().done(undefined, errors.onUnexpectedError); return; } @@ -189,7 +172,7 @@ export class DebugService implements debug.IDebugService { let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info; const { args, stack } = parse(extensionOutput); - let source: debug.IReplElementSource; + let source: IReplElementSource; if (stack) { const frame = getFirstFrame(stack); if (frame) { @@ -264,7 +247,7 @@ export class DebugService implements debug.IDebugService { } } - private tryToAutoFocusStackFrame(thread: debug.IThread): TPromise { + tryToAutoFocusStackFrame(thread: IThread): TPromise { const callStack = thread.getCallStack(); if (!callStack.length || (this.viewModel.focusedStackFrame && this.viewModel.focusedStackFrame.thread.getId() === thread.getId())) { return TPromise.as(null); @@ -278,8 +261,8 @@ export class DebugService implements debug.IDebugService { this.focusStackFrame(stackFrameToFocus); if (thread.stoppedDetails) { - if (this.configurationService.getValue('debug').openDebug === 'openOnDebugBreak') { - this.viewletService.openViewlet(debug.VIEWLET_ID).done(undefined, errors.onUnexpectedError); + if (this.configurationService.getValue('debug').openDebug === 'openOnDebugBreak') { + this.viewletService.openViewlet(VIEWLET_ID).done(undefined, errors.onUnexpectedError); } this.windowService.focusWindow(); aria.alert(nls.localize('debuggingPaused', "Debugging paused, reason {0}, {1} {2}", thread.stoppedDetails.reason, stackFrameToFocus.source ? stackFrameToFocus.source.name : '', stackFrameToFocus.range.startLineNumber)); @@ -288,199 +271,6 @@ export class DebugService implements debug.IDebugService { return stackFrameToFocus.openInEditor(this.editorService, true); } - private registerSessionListeners(session: debug.ISession, raw: RawDebugSession): void { - this.toDisposeOnSessionEnd.get(raw.getId()).push(raw.onDidInitialize(event => { - aria.status(nls.localize('debuggingStarted', "Debugging started.")); - const sendConfigurationDone = () => { - if (raw && raw.capabilities.supportsConfigurationDoneRequest) { - return raw.configurationDone().done(null, e => { - // Disconnect the debug session on configuration done error #10596 - if (raw) { - raw.disconnect().done(undefined, errors.onUnexpectedError); - } - this.notificationService.error(e.message); - }); - } - }; - - this.sendAllBreakpoints(session).then(sendConfigurationDone, sendConfigurationDone) - .done(() => this.fetchThreads(raw), errors.onUnexpectedError); - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidStop(event => { - this.updateStateAndEmit(session.getId(), debug.State.Stopped); - this.fetchThreads(raw, event.body).done(() => { - const thread = session && session.getThread(event.body.threadId); - if (thread) { - // Call fetch call stack twice, the first only return the top stack frame. - // Second retrieves the rest of the call stack. For performance reasons #25605 - this.model.fetchCallStack(thread).then(() => { - return !event.body.preserveFocusHint ? this.tryToAutoFocusStackFrame(thread) : undefined; - }); - } - }, errors.onUnexpectedError); - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidThread(event => { - if (event.body.reason === 'started') { - // debounce to reduce threadsRequest frequency and improve performance - let scheduler = this.fetchThreadsSchedulers.get(session.getId()); - if (!scheduler) { - scheduler = new RunOnceScheduler(() => { - this.fetchThreads(raw).done(undefined, errors.onUnexpectedError); - }, 100); - this.fetchThreadsSchedulers.set(session.getId(), scheduler); - this.toDisposeOnSessionEnd.get(session.getId()).push(scheduler); - } - if (!scheduler.isScheduled()) { - scheduler.schedule(); - } - } else if (event.body.reason === 'exited') { - this.model.clearThreads(session.getId(), true, event.body.threadId); - } - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidTerminateDebugee(event => { - aria.status(nls.localize('debuggingStopped', "Debugging stopped.")); - if (session && session.getId() === event.sessionId) { - if (event.body && event.body.restart && session) { - this.restartSession(session, event.body.restart).done(null, err => this.notificationService.error(err.message)); - } else { - raw.disconnect().done(undefined, errors.onUnexpectedError); - } - } - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidContinued(event => { - const threadId = event.body.allThreadsContinued !== false ? undefined : event.body.threadId; - this.model.clearThreads(session.getId(), false, threadId); - if (this.viewModel.focusedSession.getId() === session.getId()) { - this.focusStackFrame(undefined, this.viewModel.focusedThread, this.viewModel.focusedSession); - } - this.updateStateAndEmit(session.getId(), debug.State.Running); - })); - - let outputPromises: TPromise[] = []; - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidOutput(event => { - if (!event.body) { - return; - } - - const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info; - if (event.body.category === 'telemetry') { - // only log telemetry events from debug adapter if the debug extension provided the telemetry key - // and the user opted in telemetry - if (raw.customTelemetryService && this.telemetryService.isOptedIn) { - // __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly. - raw.customTelemetryService.publicLog(event.body.output, event.body.data); - } - - return; - } - - // Make sure to append output in the correct order by properly waiting on preivous promises #33822 - const waitFor = outputPromises.slice(); - const source = event.body.source ? { - lineNumber: event.body.line, - column: event.body.column ? event.body.column : 1, - source: session.getSource(event.body.source) - } : undefined; - if (event.body.variablesReference) { - const container = new ExpressionContainer(session, event.body.variablesReference, generateUuid()); - outputPromises.push(container.getChildren().then(children => { - return TPromise.join(waitFor).then(() => children.forEach(child => { - // Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names) - child.name = null; - this.logToRepl(child, outputSeverity, source); - })); - })); - } else if (typeof event.body.output === 'string') { - TPromise.join(waitFor).then(() => this.logToRepl(event.body.output, outputSeverity, source)); - } - TPromise.join(outputPromises).then(() => outputPromises = []); - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidBreakpoint(event => { - const id = event.body && event.body.breakpoint ? event.body.breakpoint.id : undefined; - const breakpoint = this.model.getBreakpoints().filter(bp => bp.idFromAdapter === id).pop(); - const functionBreakpoint = this.model.getFunctionBreakpoints().filter(bp => bp.idFromAdapter === id).pop(); - - if (event.body.reason === 'new' && event.body.breakpoint.source) { - const source = session.getSource(event.body.breakpoint.source); - const bps = this.model.addBreakpoints(source.uri, [{ - column: event.body.breakpoint.column, - enabled: true, - lineNumber: event.body.breakpoint.line, - }], false); - if (bps.length === 1) { - this.model.updateBreakpoints({ [bps[0].getId()]: event.body.breakpoint }); - } - } - - if (event.body.reason === 'removed') { - if (breakpoint) { - this.model.removeBreakpoints([breakpoint]); - } - if (functionBreakpoint) { - this.model.removeFunctionBreakpoints(functionBreakpoint.getId()); - } - } - - if (event.body.reason === 'changed') { - if (breakpoint) { - if (!breakpoint.column) { - event.body.breakpoint.column = undefined; - } - this.model.setBreakpointSessionData(session.getId(), { [breakpoint.getId()]: event.body.breakpoint }); - } - if (functionBreakpoint) { - this.model.setBreakpointSessionData(session.getId(), { [functionBreakpoint.getId()]: event.body.breakpoint }); - } - } - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidExitAdapter(event => { - // 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905 - if (strings.equalsIgnoreCase(session.configuration.type, 'extensionhost') && this.sessionStates.get(session.getId()) === debug.State.Running && - session && session.raw.root && session.configuration.noDebug) { - this.broadcastService.broadcast({ - channel: EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, - payload: [session.raw.root.uri.fsPath] - }); - } - if (session && session.getId() === event.sessionId) { - this.onExitAdapter(raw); - } - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidLoadedSource(event => { - this._onDidLoadedSource.fire({ - session: session, - reason: event.body.reason, - source: session.getSource(event.body.source) - }); - })); - - this.toDisposeOnSessionEnd.get(session.getId()).push(raw.onDidCustomEvent(event => { - this._onDidCustomEvent.fire(event); - })); - } - - private fetchThreads(session: RawDebugSession, stoppedDetails?: debug.IRawStoppedDetails): TPromise { - return session.threads().then(response => { - if (response && response.body && response.body.threads) { - response.body.threads.forEach(thread => { - this.model.rawUpdate({ - sessionId: session.getId(), - threadId: thread.id, - thread, - stoppedDetails: stoppedDetails && thread.id === stoppedDetails.threadId ? stoppedDetails : undefined - }); - }); - } - }); - } - private loadBreakpoints(): Breakpoint[] { let result: Breakpoint[]; try { @@ -525,64 +315,28 @@ export class DebugService implements debug.IDebugService { return result || []; } - public get state(): debug.State { - const focusedThread = this.viewModel.focusedThread; - if (focusedThread && focusedThread.stopped) { - return debug.State.Stopped; - } + get state(): State { const focusedSession = this.viewModel.focusedSession; - if (focusedSession && this.sessionStates.has(focusedSession.getId())) { - return this.sessionStates.get(focusedSession.getId()); - } - if (this.sessionStates.size > 0) { - return debug.State.Initializing; + if (focusedSession) { + return focusedSession.state; } - return debug.State.Inactive; + return State.Inactive; } - public get onDidChangeState(): Event { + get onDidChangeState(): Event { return this._onDidChangeState.event; } - public get onDidNewSession(): Event { + get onDidNewSession(): Event { return this._onDidNewSession.event; } - public get onDidEndSession(): Event { + get onDidEndSession(): Event { return this._onDidEndSession.event; } - public get onDidLoadedSource(): Event { - return this._onDidLoadedSource.event; - } - - public get onDidCustomEvent(): Event { - return this._onDidCustomEvent.event; - } - - private updateStateAndEmit(sessionId?: string, newState?: debug.State): void { - if (sessionId) { - if (newState === debug.State.Inactive) { - this.sessionStates.delete(sessionId); - } else { - this.sessionStates.set(sessionId, newState); - } - } - - const state = this.state; - if (this.previousState !== state) { - const stateLabel = debug.State[state]; - if (stateLabel) { - this.debugState.set(stateLabel.toLowerCase()); - this.inDebugMode.set(state !== debug.State.Inactive); - } - this.previousState = state; - this._onDidChangeState.fire(state); - } - } - - public focusStackFrame(stackFrame: debug.IStackFrame, thread?: debug.IThread, session?: debug.ISession, explicit?: boolean): void { + focusStackFrame(stackFrame: IStackFrame, thread?: IThread, session?: ISession, explicit?: boolean): void { if (!session) { if (stackFrame || thread) { session = stackFrame ? stackFrame.thread.session : thread.session; @@ -609,10 +363,9 @@ export class DebugService implements debug.IDebugService { } this.viewModel.setFocus(stackFrame, thread, session, explicit); - this.updateStateAndEmit(); } - public enableOrDisableBreakpoints(enable: boolean, breakpoint?: debug.IEnablement): TPromise { + enableOrDisableBreakpoints(enable: boolean, breakpoint?: IEnablement): TPromise { if (breakpoint) { this.model.setEnablement(breakpoint, enable); if (breakpoint instanceof Breakpoint) { @@ -628,14 +381,14 @@ export class DebugService implements debug.IDebugService { return this.sendAllBreakpoints(); } - public addBreakpoints(uri: uri, rawBreakpoints: debug.IBreakpointData[]): TPromise { + addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): TPromise { const breakpoints = this.model.addBreakpoints(uri, rawBreakpoints); breakpoints.forEach(bp => aria.status(nls.localize('breakpointAdded', "Added breakpoint, line {0}, file {1}", bp.lineNumber, uri.fsPath))); return this.sendBreakpoints(uri).then(() => breakpoints); } - public updateBreakpoints(uri: uri, data: { [id: string]: DebugProtocol.Breakpoint }, sendOnResourceSaved: boolean): void { + updateBreakpoints(uri: uri, data: { [id: string]: DebugProtocol.Breakpoint }, sendOnResourceSaved: boolean): void { this.model.updateBreakpoints(data); if (sendOnResourceSaved) { this.breakpointsToSendOnResourceSaved.add(uri.toString()); @@ -644,7 +397,7 @@ export class DebugService implements debug.IDebugService { } } - public removeBreakpoints(id?: string): TPromise { + removeBreakpoints(id?: string): TPromise { const toRemove = this.model.getBreakpoints().filter(bp => !id || bp.getId() === id); toRemove.forEach(bp => aria.status(nls.localize('breakpointRemoved', "Removed breakpoint, line {0}, file {1}", bp.lineNumber, bp.uri.fsPath))); const urisToClear = distinct(toRemove, bp => bp.uri.toString()).map(bp => bp.uri); @@ -654,37 +407,37 @@ export class DebugService implements debug.IDebugService { return TPromise.join(urisToClear.map(uri => this.sendBreakpoints(uri))); } - public setBreakpointsActivated(activated: boolean): TPromise { + setBreakpointsActivated(activated: boolean): TPromise { this.model.setBreakpointsActivated(activated); return this.sendAllBreakpoints(); } - public addFunctionBreakpoint(name?: string, id?: string): void { + addFunctionBreakpoint(name?: string, id?: string): void { const newFunctionBreakpoint = this.model.addFunctionBreakpoint(name || '', id); this.viewModel.setSelectedFunctionBreakpoint(newFunctionBreakpoint); } - public renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise { + renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise { this.model.renameFunctionBreakpoint(id, newFunctionName); return this.sendFunctionBreakpoints(); } - public removeFunctionBreakpoints(id?: string): TPromise { + removeFunctionBreakpoints(id?: string): TPromise { this.model.removeFunctionBreakpoints(id); return this.sendFunctionBreakpoints(); } - public addReplExpression(name: string): TPromise { + addReplExpression(name: string): TPromise { return this.model.addReplExpression(this.viewModel.focusedSession, this.viewModel.focusedStackFrame, name) // Evaluate all watch expressions and fetch variables again since repl evaluation might have changed some. .then(() => this.focusStackFrame(this.viewModel.focusedStackFrame, this.viewModel.focusedThread, this.viewModel.focusedSession)); } - public removeReplExpressions(): void { + removeReplExpressions(): void { this.model.removeReplExpressions(); } - public logToRepl(value: string | debug.IExpression, sev = severity.Info, source?: debug.IReplElementSource): void { + logToRepl(value: string | IExpression, sev = severity.Info, source?: IReplElementSource): void { const clearAnsiSequence = '\u001b[2J'; if (typeof value === 'string' && value.indexOf(clearAnsiSequence) >= 0) { // [2J is the ansi escape sequence for clearing the display http://ascii-table.com/ansi-escape-sequences.php @@ -696,31 +449,25 @@ export class DebugService implements debug.IDebugService { this.model.appendToRepl(value, sev, source); } - public addWatchExpression(name: string): void { + addWatchExpression(name: string): void { const we = this.model.addWatchExpression(name); this.viewModel.setSelectedExpression(we); } - public renameWatchExpression(id: string, newName: string): void { + renameWatchExpression(id: string, newName: string): void { return this.model.renameWatchExpression(id, newName); } - public moveWatchExpression(id: string, position: number): void { + moveWatchExpression(id: string, position: number): void { this.model.moveWatchExpression(id, position); } - public removeWatchExpressions(id?: string): void { + removeWatchExpressions(id?: string): void { this.model.removeWatchExpressions(id); } - public startDebugging(launch: debug.ILaunch, configOrName?: debug.IConfig | string, noDebug = false, unresolvedConfiguration?: debug.IConfig, ): TPromise { + startDebugging(launch: ILaunch, configOrName?: IConfig | string, noDebug = false, unresolvedConfiguration?: IConfig, ): TPromise { const sessionId = generateUuid(); - this.updateStateAndEmit(sessionId, debug.State.Initializing); - const wrapUpState = () => { - if (this.sessionStates.get(sessionId) === debug.State.Initializing) { - this.updateStateAndEmit(sessionId, debug.State.Inactive); - } - }; // make sure to save all files and that the configuration is up to date return this.extensionService.activateByEvent('onDebug').then(() => this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined).then(() => @@ -730,7 +477,7 @@ export class DebugService implements debug.IDebugService { this.allSessions.clear(); } - let config: debug.IConfig, compound: debug.ICompound; + let config: IConfig, compound: ICompound; if (!configOrName) { configOrName = this.configurationManager.selectedConfiguration.name; } @@ -740,7 +487,7 @@ export class DebugService implements debug.IDebugService { const sessions = this.model.getSessions(); const alreadyRunningMessage = nls.localize('configurationAlreadyRunning', "There is already a debug configuration \"{0}\" running.", configOrName); - if (sessions.some(p => p.getName(false) === configOrName && (!launch || !launch.workspace || !p.raw.root || p.raw.root.uri.toString() === launch.workspace.uri.toString()))) { + if (sessions.some(s => s.getName(false) === configOrName && (!launch || !launch.workspace || !s.root || s.root.uri.toString() === launch.workspace.uri.toString()))) { return TPromise.wrapError(new Error(alreadyRunningMessage)); } if (compound && compound.configurations && sessions.some(p => compound.configurations.indexOf(p.getName(false)) !== -1)) { @@ -762,7 +509,7 @@ export class DebugService implements debug.IDebugService { return TPromise.as(null); } - let launchForName: debug.ILaunch; + let launchForName: ILaunch; if (typeof configData === 'string') { const launchesContainingName = this.configurationManager.getLaunches().filter(l => !!l.getConfiguration(name)); if (launchesContainingName.length === 1) { @@ -799,7 +546,7 @@ export class DebugService implements debug.IDebugService { type = config.type; } else { // a no-folder workspace has no launch.config - config = {}; + config = {}; } unresolvedConfiguration = unresolvedConfiguration || deepClone(config); @@ -820,13 +567,10 @@ export class DebugService implements debug.IDebugService { }) ).then(() => undefined); }) - ))).then(() => wrapUpState(), err => { - wrapUpState(); - return TPromise.wrapError(err); - }); + ))); } - private substituteVariables(launch: debug.ILaunch | undefined, config: debug.IConfig): TPromise { + private substituteVariables(launch: ILaunch | undefined, config: IConfig): TPromise { const dbg = this.configurationManager.getDebugger(config.type); if (dbg) { let folder: IWorkspaceFolder = undefined; @@ -848,7 +592,7 @@ export class DebugService implements debug.IDebugService { return TPromise.as(config); } - private createSession(launch: debug.ILaunch, config: debug.IConfig, unresolvedConfig: debug.IConfig, sessionId: string): TPromise { + private createSession(launch: ILaunch, config: IConfig, unresolvedConfig: IConfig, sessionId: string): TPromise { return this.textFileService.saveAll().then(() => this.substituteVariables(launch, config).then(resolvedConfig => { @@ -871,8 +615,6 @@ export class DebugService implements debug.IDebugService { return this.showError(message); } - this.toDisposeOnSessionEnd.set(sessionId, []); - const workspace = launch ? launch.workspace : undefined; return this.runTask(sessionId, workspace, resolvedConfig.preLaunchTask, resolvedConfig, unresolvedConfig, () => this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, sessionId) @@ -890,45 +632,16 @@ export class DebugService implements debug.IDebugService { ); } - private initializeRawSession(root: IWorkspaceFolder, configuration: { resolved: debug.IConfig, unresolved: debug.IConfig }, sessionId: string, session?: Session): TPromise { - const dbg = this.configurationManager.getDebugger(configuration.resolved.type); - return dbg.getCustomTelemetryService().then(customTelemetryService => { - - const raw = this.instantiationService.createInstance(RawDebugSession, sessionId, configuration.resolved.debugServer, dbg, customTelemetryService, root); - if (!session) { - session = new Session(configuration, raw); - this.model.addSession(session); - this.allSessions.set(session.getId(), session); - } else { - session.raw = raw; - } - this.registerSessionListeners(session, raw); - - return raw.initialize({ - clientID: 'vscode', - clientName: product.nameLong, - adapterID: configuration.resolved.type, - pathFormat: 'path', - linesStartAt1: true, - columnsStartAt1: true, - supportsVariableType: true, // #8858 - supportsVariablePaging: true, // #9537 - supportsRunInTerminalRequest: true, // #10574 - locale: platform.locale - }).then((result: DebugProtocol.InitializeResponse) => { - this.model.setExceptionBreakpoints(raw.capabilities.exceptionBreakpointFilters); - return session; - }); - }); - } - - private doCreateSession(root: IWorkspaceFolder, configuration: { resolved: debug.IConfig, unresolved: debug.IConfig }, sessionId: string): TPromise { + private doCreateSession(root: IWorkspaceFolder, configuration: { resolved: IConfig, unresolved: IConfig }, sessionId: string): TPromise { const resolved = configuration.resolved; resolved.__sessionId = sessionId; - const dbg = this.configurationManager.getDebugger(resolved.type); - return this.initializeRawSession(root, configuration, sessionId).then(session => { + const dbgr = this.configurationManager.getDebugger(resolved.type); + const session = this.instantiationService.createInstance(Session, sessionId, configuration, root, this.model); + this.allSessions.set(sessionId, session); + return session.initialize(dbgr).then(() => { + this.registerSessionListeners(session); const raw = session.raw; return (resolved.request === 'attach' ? raw.attach(resolved) : raw.launch(resolved)) .then((result: DebugProtocol.Response) => { @@ -938,15 +651,15 @@ export class DebugService implements debug.IDebugService { this.focusStackFrame(undefined, undefined, session); this._onDidNewSession.fire(session); - const internalConsoleOptions = resolved.internalConsoleOptions || this.configurationService.getValue('debug').internalConsoleOptions; + const internalConsoleOptions = resolved.internalConsoleOptions || this.configurationService.getValue('debug').internalConsoleOptions; if (internalConsoleOptions === 'openOnSessionStart' || (this.firstSessionStart && internalConsoleOptions === 'openOnFirstSessionStart')) { - this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); + this.panelService.openPanel(REPL_ID, false).done(undefined, errors.onUnexpectedError); } - const openDebug = this.configurationService.getValue('debug').openDebug; + const openDebug = this.configurationService.getValue('debug').openDebug; // Open debug viewlet based on the visibility of the side bar and openDebug setting if (openDebug === 'openOnSessionStart' || (openDebug === 'openOnFirstSessionStart' && this.firstSessionStart)) { - this.viewletService.openViewlet(debug.VIEWLET_ID); + this.viewletService.openViewlet(VIEWLET_ID); } this.firstSessionStart = false; @@ -954,7 +667,6 @@ export class DebugService implements debug.IDebugService { if (this.model.getSessions().length > 1) { this.viewModel.setMultiSessionView(true); } - this.updateStateAndEmit(raw.getId(), debug.State.Running); /* __GDPR__ "debugSessionStart" : { @@ -972,9 +684,9 @@ export class DebugService implements debug.IDebugService { breakpointCount: this.model.getBreakpoints().length, exceptionBreakpoints: this.model.getExceptionBreakpoints(), watchExpressionsCount: this.model.getWatchExpressions().length, - extensionName: dbg.extensionDescription.id, - isBuiltin: dbg.extensionDescription.isBuiltin, - launchJsonExists: root && !!this.configurationService.getValue('launch', { resource: root.uri }) + extensionName: dbgr.extensionDescription.id, + isBuiltin: dbgr.extensionDescription.isBuiltin, + launchJsonExists: root && !!this.configurationService.getValue('launch', { resource: root.uri }) }); }).then(() => session, (error: Error | string) => { if (errors.isPromiseCanceledError(error)) { @@ -990,16 +702,15 @@ export class DebugService implements debug.IDebugService { } */ this.telemetryService.publicLog('debugMisconfiguration', { type: resolved ? resolved.type : undefined, error: errorMessage }); - this.updateStateAndEmit(raw.getId(), debug.State.Inactive); if (!raw.disconnected) { raw.disconnect(); } else if (session) { - this.model.removeSession(session.getId()); + dispose(session); } // Show the repl if some error got logged there #5870 if (this.model.getReplElements().length > 0) { - this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); + this.panelService.openPanel(REPL_ID, false).done(undefined, errors.onUnexpectedError); } this.showError(errorMessage, errors.isErrorWithActions(error) ? error.actions : []); @@ -1008,6 +719,83 @@ export class DebugService implements debug.IDebugService { }); } + private onStateChange(): void { + const state = this.state; + if (this.previousState !== state) { + const stateLabel = State[state]; + if (stateLabel) { + this.debugState.set(stateLabel.toLowerCase()); + this.inDebugMode.set(state !== State.Inactive); + } + this.previousState = state; + this._onDidChangeState.fire(state); + } + } + + private registerSessionListeners(session: Session): void { + const toDispose: IDisposable[] = []; + + toDispose.push(session.onDidChangeState((state) => { + if (state === State.Running && this.viewModel.focusedSession.getId() === session.getId()) { + this.focusStackFrame(undefined); + } + this.onStateChange(); + })); + + toDispose.push(session.onDidExitAdapter(() => { + // 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905 + if (equalsIgnoreCase(session.configuration.type, 'extensionhost') && session.state === State.Running && session.configuration.noDebug) { + this.broadcastService.broadcast({ + channel: EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, + payload: [session.root.uri.fsPath] + }); + } + + + const breakpoints = this.model.getBreakpoints(); + /* __GDPR__ + "debugSessionStop" : { + "type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "sessionLengthInSeconds": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + this.telemetryService.publicLog('debugSessionStop', { + type: session && session.configuration.type, + success: (session.raw).emittedStopped || breakpoints.length === 0, + sessionLengthInSeconds: (session.raw).getLengthInSeconds(), + breakpointCount: breakpoints.length, + watchExpressionsCount: this.model.getWatchExpressions().length + }); + + if (session.configuration.postDebugTask) { + this.doRunTask(session.getId(), session.root, session.configuration.postDebugTask).done(undefined, err => + this.notificationService.error(err) + ); + } + toDispose.push(session); + dispose(toDispose); + this._onDidEndSession.fire(session); + + const focusedSession = this.viewModel.focusedSession; + if (focusedSession && focusedSession.getId() === session.getId()) { + this.focusStackFrame(null); + } + + if (this.model.getSessions().length === 0) { + this.debugType.reset(); + this.viewModel.setMultiSessionView(false); + + if (this.partService.isVisible(Parts.SIDEBAR_PART) && this.configurationService.getValue('debug').openExplorerOnEnd) { + this.viewletService.openViewlet(EXPLORER_VIEWLET_ID).done(null, errors.onUnexpectedError); + } + } + + })); + } + private showError(message: string, actions: IAction[] = []): TPromise { const configureAction = this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL); actions.push(configureAction); @@ -1020,7 +808,7 @@ export class DebugService implements debug.IDebugService { }); } - private runTask(sessionId: string, root: IWorkspaceFolder, taskId: string | TaskIdentifier, config: debug.IConfig, unresolvedConfig: debug.IConfig, onSuccess: () => TPromise): TPromise { + private runTask(sessionId: string, root: IWorkspaceFolder, taskId: string | TaskIdentifier, config: IConfig, unresolvedConfig: IConfig, onSuccess: () => TPromise): TPromise { const debugAnywayAction = new Action('debug.debugAnyway', nls.localize('debugAnyway', "Debug Anyway"), undefined, true, () => { return this.doCreateSession(root, { resolved: config, unresolved: unresolvedConfig }, sessionId); }); @@ -1079,16 +867,12 @@ export class DebugService implements debug.IDebugService { // task is already running - nothing to do. return TPromise.as(null); } - this.toDisposeOnSessionEnd.get(sessionId).push( - once(TaskEventKind.Active, this.taskService.onDidStateChange)(() => { - taskStarted = true; - }) - ); + once(TaskEventKind.Active, this.taskService.onDidStateChange)((taskEvent) => { + taskStarted = true; + }); const taskPromise = this.taskService.run(task); if (task.isBackground) { - return new TPromise((c, e) => this.toDisposeOnSessionEnd.get(sessionId).push( - once(TaskEventKind.Inactive, this.taskService.onDidStateChange)(() => c(null))) - ); + return new TPromise((c, e) => once(TaskEventKind.Inactive, this.taskService.onDidStateChange)(() => c(null))); } return taskPromise; @@ -1112,16 +896,16 @@ export class DebugService implements debug.IDebugService { }); } - public sourceIsNotAvailable(uri: uri): void { + sourceIsNotAvailable(uri: uri): void { this.model.sourceIsNotAvailable(uri); } - public restartSession(session: debug.ISession, restartData?: any): TPromise { + restartSession(session: ISession, restartData?: any): TPromise { return this.textFileService.saveAll().then(() => { const unresolvedConfiguration = (session).unresolvedConfiguration; if (session.raw.capabilities.supportsRestartRequest) { - return this.runTask(session.getId(), session.raw.root, session.configuration.postDebugTask, session.configuration, unresolvedConfiguration, - () => this.runTask(session.getId(), session.raw.root, session.configuration.preLaunchTask, session.configuration, unresolvedConfiguration, + return this.runTask(session.getId(), session.root, session.configuration.postDebugTask, session.configuration, unresolvedConfiguration, + () => this.runTask(session.getId(), session.root, session.configuration.preLaunchTask, session.configuration, unresolvedConfiguration, () => session.raw.custom('restart', null))); } @@ -1131,11 +915,11 @@ export class DebugService implements debug.IDebugService { this.skipRunningTask = !!restartData; // If the restart is automatic disconnect, otherwise send the terminate signal #55064 - return (!!restartData ? (session.raw).disconnect(true) : session.raw.terminate(true)).then(() => { - if (strings.equalsIgnoreCase(session.configuration.type, 'extensionHost') && session.raw.root) { + return (!!restartData ? session.raw.disconnect(true) : session.raw.terminate(true)).then(() => { + if (equalsIgnoreCase(session.configuration.type, 'extensionHost') && session.root) { return this.broadcastService.broadcast({ channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, - payload: [session.raw.root.uri.fsPath] + payload: [session.root.uri.fsPath] }); } @@ -1144,7 +928,7 @@ export class DebugService implements debug.IDebugService { // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration let configToUse = session.configuration; - const launch = session.raw.root ? this.configurationManager.getLaunch(session.raw.root.uri) : undefined; + const launch = session.root ? this.configurationManager.getLaunch(session.root.uri) : undefined; if (launch) { const config = launch.getConfiguration(session.configuration.name); if (config && !equals(config, unresolvedConfiguration)) { @@ -1171,7 +955,7 @@ export class DebugService implements debug.IDebugService { }); } - public stopSession(session: debug.ISession): TPromise { + stopSession(session: ISession): TPromise { if (session) { return session.raw.terminate(); } @@ -1181,80 +965,32 @@ export class DebugService implements debug.IDebugService { return TPromise.join(sessions.map(s => s.raw.terminate(false))); } - this.sessionStates.clear(); this._onDidChangeState.fire(); return undefined; } - private onExitAdapter(raw: RawDebugSession): void { - const breakpoints = this.model.getBreakpoints(); - const session = this.model.getSessions().filter(p => p.getId() === raw.getId()).pop(); - /* __GDPR__ - "debugSessionStop" : { - "type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "success": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "sessionLengthInSeconds": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "watchExpressionsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } - } - */ - this.telemetryService.publicLog('debugSessionStop', { - type: session && session.configuration.type, - success: raw.emittedStopped || breakpoints.length === 0, - sessionLengthInSeconds: raw.getLengthInSeconds(), - breakpointCount: breakpoints.length, - watchExpressionsCount: this.model.getWatchExpressions().length - }); - - this.model.removeSession(raw.getId()); - if (session) { - this._onDidEndSession.fire(session); - if (session.configuration.postDebugTask) { - this.doRunTask(session.getId(), session.raw.root, session.configuration.postDebugTask).done(undefined, err => - this.notificationService.error(err) - ); - } - } - - lifecycle.dispose(this.toDisposeOnSessionEnd.get(raw.getId())); - const focusedSession = this.viewModel.focusedSession; - if (focusedSession && focusedSession.getId() === raw.getId()) { - this.focusStackFrame(null); - } - this.updateStateAndEmit(raw.getId(), debug.State.Inactive); - - if (this.model.getSessions().length === 0) { - this.debugType.reset(); - this.viewModel.setMultiSessionView(false); - - if (this.partService.isVisible(Parts.SIDEBAR_PART) && this.configurationService.getValue('debug').openExplorerOnEnd) { - this.viewletService.openViewlet(EXPLORER_VIEWLET_ID).done(null, errors.onUnexpectedError); - } - } - } - - public getModel(): debug.IModel { + getModel(): IModel { return this.model; } - public getViewModel(): debug.IViewModel { + getViewModel(): IViewModel { return this.viewModel; } - public getConfigurationManager(): debug.IConfigurationManager { + getConfigurationManager(): IConfigurationManager { return this.configurationManager; } - private sendAllBreakpoints(session?: debug.ISession): TPromise { + private sendAllBreakpoints(session?: ISession): TPromise { return TPromise.join(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session))) .then(() => this.sendFunctionBreakpoints(session)) // send exception breakpoints at the end since some debug adapters rely on the order .then(() => this.sendExceptionBreakpoints(session)); } - private sendBreakpoints(modelUri: uri, sourceModified = false, session?: debug.ISession): TPromise { + private sendBreakpoints(modelUri: uri, sourceModified = false, session?: ISession): TPromise { - const sendBreakpointsToSession = (session: debug.ISession): TPromise => { + const sendBreakpointsToSession = (session: ISession): TPromise => { const raw = session.raw; if (!raw.readyForBreakpoints) { return TPromise.as(null); @@ -1291,15 +1027,15 @@ export class DebugService implements debug.IDebugService { for (let i = 0; i < breakpointsToSend.length; i++) { data[breakpointsToSend[i].getId()] = response.body.breakpoints[i]; } - this.model.setBreakpointSessionData(raw.getId(), data); + this.model.setBreakpointSessionData(session.getId(), data); }); }; return this.sendToOneOrAllSessions(session, sendBreakpointsToSession); } - private sendFunctionBreakpoints(session?: debug.ISession): TPromise { - const sendFunctionBreakpointsToSession = (session: debug.ISession): TPromise => { + private sendFunctionBreakpoints(session?: ISession): TPromise { + const sendFunctionBreakpointsToSession = (session: ISession): TPromise => { const raw = session.raw; if (!raw.readyForBreakpoints || !raw.capabilities.supportsFunctionBreakpoints) { return TPromise.as(null); @@ -1315,15 +1051,15 @@ export class DebugService implements debug.IDebugService { for (let i = 0; i < breakpointsToSend.length; i++) { data[breakpointsToSend[i].getId()] = response.body.breakpoints[i]; } - this.model.setBreakpointSessionData(raw.getId(), data); + this.model.setBreakpointSessionData(session.getId(), data); }); }; return this.sendToOneOrAllSessions(session, sendFunctionBreakpointsToSession); } - private sendExceptionBreakpoints(session?: debug.ISession): TPromise { - const sendExceptionBreakpointsToSession = (session: debug.ISession): TPromise => { + private sendExceptionBreakpoints(session?: ISession): TPromise { + const sendExceptionBreakpointsToSession = (session: ISession): TPromise => { const raw = session.raw; if (!raw.readyForBreakpoints || this.model.getExceptionBreakpoints().length === 0) { return TPromise.as(null); @@ -1336,7 +1072,7 @@ export class DebugService implements debug.IDebugService { return this.sendToOneOrAllSessions(session, sendExceptionBreakpointsToSession); } - private sendToOneOrAllSessions(session: debug.ISession, send: (session: debug.ISession) => TPromise): TPromise { + private sendToOneOrAllSessions(session: ISession, send: (session: ISession) => TPromise): TPromise { if (session) { return send(session); } @@ -1395,8 +1131,7 @@ export class DebugService implements debug.IDebugService { } } - public dispose(): void { - this.toDisposeOnSessionEnd.forEach(toDispose => lifecycle.dispose(toDispose)); - this.toDispose = lifecycle.dispose(this.toDispose); + dispose(): void { + this.toDispose = dispose(this.toDispose); } } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts index 75170c00238..1be9dbc2494 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts @@ -5,53 +5,95 @@ import uri from 'vs/base/common/uri'; import * as resources from 'vs/base/common/resources'; +import * as nls from 'vs/nls'; +import * as platform from 'vs/base/common/platform'; +import * as errors from 'vs/base/common/errors'; +import severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; +import { Event, Emitter } from 'vs/base/common/event'; import { ISuggestion } from 'vs/editor/common/modes'; import { Position } from 'vs/editor/common/core/position'; -import { ITreeElement, ISession, IConfig, IRawSession, IThread, IRawModelUpdate, SessionState } from 'vs/workbench/parts/debug/common/debug'; +import * as aria from 'vs/base/browser/ui/aria/aria'; +import { ISession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, IRawSession, LoadedSourceEvent, DebugEvent } from 'vs/workbench/parts/debug/common/debug'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { mixin } from 'vs/base/common/objects'; -import { Thread, ExpressionContainer } from 'vs/workbench/parts/debug/common/debugModel'; +import { Thread, ExpressionContainer, Model } from 'vs/workbench/parts/debug/common/debugModel'; +import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { Debugger } from 'vs/workbench/parts/debug/node/debugger'; +import product from 'vs/platform/node/product'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { generateUuid } from 'vs/base/common/uuid'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; export class Session implements ISession { - private sources: Map; - private threads: Map; + private sources = new Map(); + private threads = new Map(); + private rawListeners: IDisposable[] = []; + private fetchThreadsScheduler: RunOnceScheduler; + private _raw: RawDebugSession; + private _state: State; + private readonly _onDidLoadedSource = new Emitter(); + private readonly _onDidCustomEvent = new Emitter(); + private readonly _onDidChangeState = new Emitter(); + private readonly _onDidExitAdapter = new Emitter(); - constructor(private _configuration: { resolved: IConfig, unresolved: IConfig }, private session: IRawSession & ITreeElement) { - this.threads = new Map(); - this.sources = new Map(); + constructor( + private id: string, + private _configuration: { resolved: IConfig, unresolved: IConfig }, + public root: IWorkspaceFolder, + private model: Model, + @IInstantiationService private instantiationService: IInstantiationService, + @INotificationService private notificationService: INotificationService, + @IDebugService private debugService: IDebugService, + @ITelemetryService private telemetryService: ITelemetryService, + ) { + this.model.addSession(this); + this.state = State.Initializing; } - public get configuration(): IConfig { + get raw(): IRawSession { + return this._raw; + } + + get configuration(): IConfig { return this._configuration.resolved; } - public get unresolvedConfiguration(): IConfig { + get unresolvedConfiguration(): IConfig { return this._configuration.unresolved; } - public get raw(): IRawSession & ITreeElement { - return this.session; + getName(includeRoot: boolean): string { + return includeRoot && this.root ? `${this.configuration.name} (${resources.basenameOrAuthority(this.root.uri)})` : this.configuration.name; } - public set raw(value: IRawSession & ITreeElement) { - this.session = value; + get state(): State { + return this._state; } - public getName(includeRoot: boolean): string { - return includeRoot && this.raw.root ? `${this.configuration.name} (${resources.basenameOrAuthority(this.raw.root.uri)})` : this.configuration.name; + set state(value: State) { + this._state = value; + this._onDidChangeState.fire(value); } - public get state(): SessionState { - return this.configuration.type === 'attach' ? SessionState.ATTACH : SessionState.LAUNCH; + get onDidChangeState(): Event { + return this._onDidChangeState.event; } - public getSourceForUri(modelUri: uri): Source { + getId(): string { + return this.id; + } + + getSourceForUri(modelUri: uri): Source { return this.sources.get(modelUri.toString()); } - public getSource(raw: DebugProtocol.Source): Source { + getSource(raw: DebugProtocol.Source): Source { let source = new Source(raw, this.getId()); if (this.sources.has(source.uri.toString())) { source = this.sources.get(source.uri.toString()); @@ -67,29 +109,37 @@ export class Session implements ISession { return source; } - public getThread(threadId: number): Thread { + getThread(threadId: number): Thread { return this.threads.get(threadId); } - public getAllThreads(): IThread[] { + getAllThreads(): IThread[] { const result: IThread[] = []; this.threads.forEach(t => result.push(t)); return result; } - public getLoadedSources(): TPromise { - return this.raw.loadedSources({}).then(response => { + getLoadedSources(): TPromise { + return this._raw.loadedSources({}).then(response => { return response.body.sources.map(src => this.getSource(src)); - }, error => { + }, () => { return []; }); } - public getId(): string { - return this.session.getId(); + get onDidLoadedSource(): Event { + return this._onDidLoadedSource.event; } - public rawUpdate(data: IRawModelUpdate): void { + get onDidCustomEvent(): Event { + return this._onDidCustomEvent.event; + } + + get onDidExitAdapter(): Event { + return this._onDidExitAdapter.event; + } + + rawUpdate(data: IRawModelUpdate): void { if (data.thread && !this.threads.has(data.threadId)) { // A new thread came in, initialize it. @@ -118,7 +168,7 @@ export class Session implements ISession { } } - public clearThreads(removeThreads: boolean, reference: number = undefined): void { + clearThreads(removeThreads: boolean, reference: number = undefined): void { if (reference !== undefined && reference !== null) { if (this.threads.has(reference)) { const thread = this.threads.get(reference); @@ -144,12 +194,12 @@ export class Session implements ISession { } } - public completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise { - if (!this.raw.capabilities.supportsCompletionsRequest) { + completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise { + if (!this._raw.capabilities.supportsCompletionsRequest) { return TPromise.as([]); } - return this.raw.completions({ + return this._raw.completions({ frameId, text, column: position.column, @@ -173,4 +223,214 @@ export class Session implements ISession { return result; }, () => []); } + + initialize(dbgr: Debugger): TPromise { + return dbgr.getCustomTelemetryService().then(customTelemetryService => { + if (this._raw) { + // If there was already a connection make sure to remove old listeners + dispose(this.rawListeners); + } + this._raw = this.instantiationService.createInstance(RawDebugSession, this.id, this._configuration.resolved.debugServer, dbgr, customTelemetryService, this.root); + this.registerListeners(); + + return this._raw.initialize({ + clientID: 'vscode', + clientName: product.nameLong, + adapterID: this.configuration.type, + pathFormat: 'path', + linesStartAt1: true, + columnsStartAt1: true, + supportsVariableType: true, // #8858 + supportsVariablePaging: true, // #9537 + supportsRunInTerminalRequest: true, // #10574 + locale: platform.locale + }).then(() => { + this.state = State.Running; + this.model.setExceptionBreakpoints(this._raw.capabilities.exceptionBreakpointFilters); + }); + }); + } + + private registerListeners(): void { + this.rawListeners.push(this._raw.onDidInitialize(() => { + aria.status(nls.localize('debuggingStarted', "Debugging started.")); + const sendConfigurationDone = () => { + if (this._raw && this._raw.capabilities.supportsConfigurationDoneRequest) { + return this._raw.configurationDone().done(null, e => { + // Disconnect the debug session on configuration done error #10596 + if (this._raw) { + this._raw.disconnect().done(undefined, errors.onUnexpectedError); + } + this.notificationService.error(e.message); + }); + } + }; + + // Send all breakpoints + this.debugService.setBreakpointsActivated(true).then(sendConfigurationDone, sendConfigurationDone) + .done(() => this.fetchThreads(), errors.onUnexpectedError); + })); + + this.rawListeners.push(this._raw.onDidStop(event => { + this.state = State.Stopped; + this.fetchThreads(event.body).done(() => { + const thread = this.getThread(event.body.threadId); + if (thread) { + // Call fetch call stack twice, the first only return the top stack frame. + // Second retrieves the rest of the call stack. For performance reasons #25605 + this.model.fetchCallStack(thread).then(() => { + return !event.body.preserveFocusHint ? this.debugService.tryToAutoFocusStackFrame(thread) : undefined; + }); + } + }, errors.onUnexpectedError); + })); + + this.rawListeners.push(this._raw.onDidThread(event => { + if (event.body.reason === 'started') { + // debounce to reduce threadsRequest frequency and improve performance + if (!this.fetchThreadsScheduler) { + this.fetchThreadsScheduler = new RunOnceScheduler(() => { + this.fetchThreads().done(undefined, errors.onUnexpectedError); + }, 100); + this.rawListeners.push(this.fetchThreadsScheduler); + } + if (!this.fetchThreadsScheduler.isScheduled()) { + this.fetchThreadsScheduler.schedule(); + } + } else if (event.body.reason === 'exited') { + this.model.clearThreads(this.getId(), true, event.body.threadId); + } + })); + + this.rawListeners.push(this._raw.onDidTerminateDebugee(event => { + aria.status(nls.localize('debuggingStopped', "Debugging stopped.")); + if (event.body && event.body.restart) { + this.debugService.restartSession(this, event.body.restart).done(null, err => this.notificationService.error(err.message)); + } else { + this._raw.disconnect().done(undefined, errors.onUnexpectedError); + } + })); + + this.rawListeners.push(this._raw.onDidContinued(event => { + const threadId = event.body.allThreadsContinued !== false ? undefined : event.body.threadId; + this.model.clearThreads(this.getId(), false, threadId); + this.state = State.Running; + })); + + let outputPromises: TPromise[] = []; + this.rawListeners.push(this._raw.onDidOutput(event => { + if (!event.body) { + return; + } + + const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info; + if (event.body.category === 'telemetry') { + // only log telemetry events from debug adapter if the debug extension provided the telemetry key + // and the user opted in telemetry + if (this._raw.customTelemetryService && this.telemetryService.isOptedIn) { + // __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly. + this._raw.customTelemetryService.publicLog(event.body.output, event.body.data); + } + + return; + } + + // Make sure to append output in the correct order by properly waiting on preivous promises #33822 + const waitFor = outputPromises.slice(); + const source = event.body.source ? { + lineNumber: event.body.line, + column: event.body.column ? event.body.column : 1, + source: this.getSource(event.body.source) + } : undefined; + if (event.body.variablesReference) { + const container = new ExpressionContainer(this, event.body.variablesReference, generateUuid()); + outputPromises.push(container.getChildren().then(children => { + return TPromise.join(waitFor).then(() => children.forEach(child => { + // Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names) + child.name = null; + this.debugService.logToRepl(child, outputSeverity, source); + })); + })); + } else if (typeof event.body.output === 'string') { + TPromise.join(waitFor).then(() => this.debugService.logToRepl(event.body.output, outputSeverity, source)); + } + TPromise.join(outputPromises).then(() => outputPromises = []); + })); + + this.rawListeners.push(this._raw.onDidBreakpoint(event => { + const id = event.body && event.body.breakpoint ? event.body.breakpoint.id : undefined; + const breakpoint = this.model.getBreakpoints().filter(bp => bp.idFromAdapter === id).pop(); + const functionBreakpoint = this.model.getFunctionBreakpoints().filter(bp => bp.idFromAdapter === id).pop(); + + if (event.body.reason === 'new' && event.body.breakpoint.source) { + const source = this.getSource(event.body.breakpoint.source); + const bps = this.model.addBreakpoints(source.uri, [{ + column: event.body.breakpoint.column, + enabled: true, + lineNumber: event.body.breakpoint.line, + }], false); + if (bps.length === 1) { + this.model.updateBreakpoints({ [bps[0].getId()]: event.body.breakpoint }); + } + } + + if (event.body.reason === 'removed') { + if (breakpoint) { + this.model.removeBreakpoints([breakpoint]); + } + if (functionBreakpoint) { + this.model.removeFunctionBreakpoints(functionBreakpoint.getId()); + } + } + + if (event.body.reason === 'changed') { + if (breakpoint) { + if (!breakpoint.column) { + event.body.breakpoint.column = undefined; + } + this.model.setBreakpointSessionData(this.getId(), { [breakpoint.getId()]: event.body.breakpoint }); + } + if (functionBreakpoint) { + this.model.setBreakpointSessionData(this.getId(), { [functionBreakpoint.getId()]: event.body.breakpoint }); + } + } + })); + + this.rawListeners.push(this._raw.onDidLoadedSource(event => { + this._onDidLoadedSource.fire({ + reason: event.body.reason, + source: this.getSource(event.body.source) + }); + })); + + this.rawListeners.push(this._raw.onDidCustomEvent(event => { + this._onDidCustomEvent.fire(event); + })); + + this.rawListeners.push(this._raw.onDidExitAdapter(() => this._onDidExitAdapter.fire())); + } + + private fetchThreads(stoppedDetails?: IRawStoppedDetails): TPromise { + return this._raw.threads().then(response => { + if (response && response.body && response.body.threads) { + response.body.threads.forEach(thread => { + this.model.rawUpdate({ + sessionId: this.getId(), + threadId: thread.id, + thread, + stoppedDetails: stoppedDetails && thread.id === stoppedDetails.threadId ? stoppedDetails : undefined + }); + }); + } + }); + } + + dispose(): void { + dispose(this.rawListeners); + this.model.removeSession(this.getId()); + if (!this._raw.disconnected) { + this._raw.disconnect().done(undefined, errors.onUnexpectedError); + } + this._raw = undefined; + } } diff --git a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts index 93891ff0b4e..c98bfcb2347 100644 --- a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts @@ -16,10 +16,9 @@ import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { formatPII } from 'vs/workbench/parts/debug/common/debugUtils'; import { SocketDebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter'; -import { SessionState, DebugEvent, IRawSession, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug'; +import { DebugEvent, IRawSession, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; - export interface SessionExitedEvent extends DebugEvent { body: { exitCode: number, @@ -48,7 +47,7 @@ export class RawDebugSession implements IRawSession { private cancellationTokens: CancellationTokenSource[]; private _capabilities: DebugProtocol.Capabilities; private allThreadsContinued: boolean; - private state: SessionState = SessionState.LAUNCH; + private isAttached: boolean; private readonly _onDidInitialize: Emitter; private readonly _onDidStop: Emitter; @@ -64,11 +63,11 @@ export class RawDebugSession implements IRawSession { private readonly _onDidEvent: Emitter; constructor( - private id: string, + private sessionId: string, private debugServerPort: number, private _debugger: Debugger, public customTelemetryService: ITelemetryService, - public root: IWorkspaceFolder, + private root: IWorkspaceFolder, @INotificationService private notificationService: INotificationService, @ITelemetryService private telemetryService: ITelemetryService, @IOutputService private outputService: IOutputService @@ -92,10 +91,6 @@ export class RawDebugSession implements IRawSession { this._onDidEvent = new Emitter(); } - public getId(): string { - return this.id; - } - public get onDidInitialize(): Event { return this._onDidInitialize.event; } @@ -239,7 +234,7 @@ export class RawDebugSession implements IRawSession { } private onDapEvent(event: DebugEvent): void { - event.sessionId = this.id; + event.sessionId = this.sessionId; if (event.event === 'loadedSource') { // most frequent comes first this._onDidLoadedSource.fire(event); @@ -293,7 +288,7 @@ export class RawDebugSession implements IRawSession { } public attach(args: DebugProtocol.AttachRequestArguments): TPromise { - this.state = SessionState.ATTACH; + this.isAttached = true; return this.send('attach', args).then(response => this.readCapabilities(response)); } @@ -352,7 +347,7 @@ export class RawDebugSession implements IRawSession { } public terminate(restart = false): TPromise { - if (this.capabilities.supportsTerminateRequest && !this.terminated && this.state === SessionState.LAUNCH) { + if (this.capabilities.supportsTerminateRequest && !this.terminated && !this.isAttached) { this.terminated = true; return this.send('terminate', { restart }); } @@ -516,13 +511,12 @@ export class RawDebugSession implements IRawSession { this.cachedInitServerP = null; } - this._onDidExitAdapter.fire({ sessionId: this.getId() }); + this._onDidExitAdapter.fire({ sessionId: this.sessionId }); this.disconnected = true; if (!this.debugAdapter || this.debugAdapter instanceof SocketDebugAdapter) { return TPromise.as(null); } - return this.debugAdapter.stopSession(); } @@ -537,6 +531,6 @@ export class RawDebugSession implements IRawSession { if (!this.disconnected) { this.notificationService.error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly")); } - this._onDidExitAdapter.fire({ sessionId: this.getId() }); + this._onDidExitAdapter.fire({ sessionId: this.sessionId }); } } diff --git a/src/vs/workbench/parts/debug/test/common/mockDebug.ts b/src/vs/workbench/parts/debug/test/common/mockDebug.ts index c9914760a19..6e272e451b8 100644 --- a/src/vs/workbench/parts/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/parts/debug/test/common/mockDebug.ts @@ -4,25 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import uri from 'vs/base/common/uri'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { Position } from 'vs/editor/common/core/position'; -import { ILaunch, IDebugService, State, DebugEvent, ISession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawSession, IBreakpoint, LoadedSourceEvent, SessionState, IThread, IRawModelUpdate } from 'vs/workbench/parts/debug/common/debug'; +import { ILaunch, IDebugService, State, DebugEvent, ISession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawSession, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate } from 'vs/workbench/parts/debug/common/debug'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { ISuggestion } from 'vs/editor/common/modes'; export class MockDebugService implements IDebugService { + public _serviceBrand: any; public get state(): State { return null; } - public get onDidCustomEvent(): Event { - return null; - } - public get onDidNewSession(): Event { return null; } @@ -35,10 +32,6 @@ export class MockDebugService implements IDebugService { return null; } - public get onDidLoadedSource(): Event { - return null; - } - public getConfigurationManager(): IConfigurationManager { return null; } @@ -115,12 +108,18 @@ export class MockDebugService implements IDebugService { public logToRepl(value: string): void { } public sourceIsNotAvailable(uri: uri): void { } + + public tryToAutoFocusStackFrame(thread: IThread): TPromise { + return TPromise.as(null); + } } export class MockSession implements ISession { + configuration: IConfig = { type: 'mock', request: 'launch' }; raw: IRawSession = new MockRawSession(); - state = SessionState.LAUNCH; + state = State.Stopped; + root: IWorkspaceFolder; getName(includeRoot: boolean): string { return 'mockname'; @@ -134,6 +133,18 @@ export class MockSession implements ISession { return null; } + get onDidCustomEvent(): Event { + return null; + } + + get onDidLoadedSource(): Event { + return null; + } + + get onDidExitAdapter(): Event { + return null; + } + getAllThreads(): ReadonlyArray { return []; } @@ -157,6 +168,8 @@ export class MockSession implements ISession { getId(): string { return 'mock'; } + + dispose(): void { } } export class MockRawSession implements IRawSession { @@ -164,12 +177,6 @@ export class MockRawSession implements IRawSession { public readyForBreakpoints = true; public emittedStopped = true; - public getId() { - return 'mockrawsession'; - } - - public root: IWorkspaceFolder; - public getLengthInSeconds(): number { return 100; } @@ -216,21 +223,6 @@ export class MockRawSession implements IRawSession { return {}; } - public get onDidEvent(): Event { - return null; - } - - public get onDidInitialize(): Event { - const emitter = new Emitter(); - return emitter.event; - } - - public get onDidExitAdapter(): Event<{ sessionId: string }> { - const emitter = new Emitter<{ sessionId: string }>(); - return emitter.event; - } - - public custom(request: string, args: any): TPromise { return TPromise.as(null); } @@ -239,6 +231,10 @@ export class MockRawSession implements IRawSession { return TPromise.as(null); } + public disconnect(restart?: boolean): TPromise { + return TPromise.as(null); + } + public threads(): TPromise { return TPromise.as(null); } diff --git a/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts b/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts index 3e448f864e7..5aa97ff564d 100644 --- a/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/electron-browser/debugModel.test.ts @@ -109,11 +109,11 @@ suite('Debug - Model', () => { test('threads simple', () => { const threadId = 1; const threadName = 'firstThread'; - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); - model.addSession(session); + const session = new Session('mock', { resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined); + assert.equal(model.getSessions().length, 1); model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: threadId, thread: { id: threadId, @@ -140,10 +140,11 @@ suite('Debug - Model', () => { const stoppedReason = 'breakpoint'; // Add the threads - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); - model.addSession(session); + const session = new Session('mock', { resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined); + session['_raw'] = rawSession; + model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: threadId1, thread: { id: threadId1, @@ -152,7 +153,7 @@ suite('Debug - Model', () => { }); model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: threadId2, thread: { id: threadId2, @@ -162,7 +163,7 @@ suite('Debug - Model', () => { // Stopped event with all threads stopped model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: threadId1, stoppedDetails: { reason: stoppedReason, @@ -230,11 +231,12 @@ suite('Debug - Model', () => { const runningThreadId = 2; const runningThreadName = 'runningThread'; const stoppedReason = 'breakpoint'; - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); - model.addSession(session); + const session = new Session('mock', { resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined); + session['_raw'] = rawSession; + // Add the threads model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: stoppedThreadId, thread: { id: stoppedThreadId, @@ -243,7 +245,7 @@ suite('Debug - Model', () => { }); model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: runningThreadId, thread: { id: runningThreadId, @@ -253,7 +255,7 @@ suite('Debug - Model', () => { // Stopped event with only one thread stopped model.rawUpdate({ - sessionId: rawSession.getId(), + sessionId: 'mock', threadId: stoppedThreadId, stoppedDetails: { reason: stoppedReason, @@ -341,7 +343,8 @@ suite('Debug - Model', () => { test('repl expressions', () => { assert.equal(model.getReplElements().length, 0); - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new Session('mock', { resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined); + session['_raw'] = rawSession; const thread = new Thread(session, 'mockthread', 1); const stackFrame = new StackFrame(thread, 1, null, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 10 }, 1); model.addReplExpression(session, stackFrame, 'myVariable').done(); @@ -360,7 +363,7 @@ suite('Debug - Model', () => { }); test('stack frame get specific source name', () => { - const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, rawSession); + const session = new Session('mock', { resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined); let firstStackFrame: StackFrame; let secondStackFrame: StackFrame; const thread = new class extends Thread { From 1f1b778104ea9338e898261d8b106489ad2d7784 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 20 Aug 2018 12:09:42 +0200 Subject: [PATCH 09/44] resource.isEqual / isEqualOrParent: use isIgnore default bahaviour --- src/vs/base/common/resources.ts | 2 +- src/vs/code/electron-main/windows.ts | 10 +++++----- src/vs/code/node/windowsFinder.ts | 10 +++++----- .../platform/backup/electron-main/backupMainService.ts | 4 ++-- .../history/electron-main/historyMainService.ts | 8 ++++---- .../parts/files/browser/editors/fileEditorTracker.ts | 6 +++--- src/vs/workbench/parts/files/common/explorerModel.ts | 2 +- .../markers/electron-browser/markersPanelActions.ts | 4 ++-- .../preferences/common/preferencesContribution.ts | 6 +++--- .../parts/snippets/electron-browser/snippetsService.ts | 2 +- .../services/configuration/node/configuration.ts | 2 +- .../configuration/node/configurationService.ts | 4 ++-- .../jsonschemas/common/jsonValidationExtensionPoint.ts | 2 +- .../services/textMate/electron-browser/TMSyntax.ts | 2 +- .../services/textfile/common/textFileEditorModel.ts | 6 +++--- .../themes/electron-browser/colorThemeStore.ts | 2 +- .../themes/electron-browser/fileIconThemeStore.ts | 2 +- .../services/workspace/node/workspaceEditingService.ts | 4 ++-- src/vs/workbench/test/workbenchTestServices.ts | 4 ++-- 19 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index cefcd007927..ac6103d1ae0 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -46,7 +46,7 @@ function isEqualAuthority(a1: string, a2: string, ignoreCase?: boolean) { return a1 === a2 || ignoreCase && a1 && a2 && equalsIgnoreCase(a1, a2); } -export function isEqual(first: URI, second: URI, ignoreCase?: boolean): boolean { +export function isEqual(first: URI, second: URI, ignoreCase = hasToIgnoreCase(first)): boolean { const identityEquals = (first === second); if (identityEquals) { return true; diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index ee30f9a282b..5c9051ca65d 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -37,7 +37,7 @@ import { normalizeNFC } from 'vs/base/common/normalization'; import URI from 'vs/base/common/uri'; import { Queue } from 'vs/base/common/async'; import { exists } from 'vs/base/node/pfs'; -import { getComparisonKey, isEqual, hasToIgnoreCase, normalizePath } from 'vs/base/common/resources'; +import { getComparisonKey, isEqual, normalizePath } from 'vs/base/common/resources'; import { endsWith } from 'vs/base/common/strings'; enum WindowError { @@ -328,7 +328,7 @@ export class WindowsManager implements IWindowsMainService { else if (!win.isExtensionDevelopmentHost && (!!win.openedWorkspace || !!win.openedFolderUri)) { this.windowsState.openedWindows.forEach(o => { const sameWorkspace = win.openedWorkspace && o.workspace && o.workspace.id === win.openedWorkspace.id; - const sameFolder = win.openedFolderUri && o.folderUri && isEqual(o.folderUri, win.openedFolderUri, hasToIgnoreCase(o.folderUri)); + const sameFolder = win.openedFolderUri && o.folderUri && isEqual(o.folderUri, win.openedFolderUri); if (sameWorkspace || sameFolder) { o.uiState = state.uiState; @@ -444,7 +444,7 @@ export class WindowsManager implements IWindowsMainService { const usedWindow = usedWindows[i]; if ( (usedWindow.openedWorkspace && workspacesToRestore.some(workspace => workspace.id === usedWindow.openedWorkspace.id)) || // skip over restored workspace - (usedWindow.openedFolderUri && foldersToRestore.some(folder => isEqual(folder, usedWindow.openedFolderUri, hasToIgnoreCase(folder)))) || // skip over restored folder + (usedWindow.openedFolderUri && foldersToRestore.some(folder => isEqual(folder, usedWindow.openedFolderUri))) || // skip over restored folder (usedWindow.backupPath && emptyToRestore.some(empty => empty === basename(usedWindow.backupPath))) // skip over restored empty window ) { continue; @@ -660,7 +660,7 @@ export class WindowsManager implements IWindowsMainService { // Open remaining ones allFoldersToOpen.forEach(folderToOpen => { - if (windowsOnFolderPath.some(win => isEqual(win.openedFolderUri, folderToOpen, hasToIgnoreCase(win.openedFolderUri)))) { + if (windowsOnFolderPath.some(win => isEqual(win.openedFolderUri, folderToOpen))) { return; // ignore folders that are already open } @@ -1324,7 +1324,7 @@ export class WindowsManager implements IWindowsMainService { // Known Folder - load from stored settings if (configuration.folderUri) { - const stateForFolder = this.windowsState.openedWindows.filter(o => o.folderUri && isEqual(o.folderUri, configuration.folderUri, hasToIgnoreCase(o.folderUri))).map(o => o.uiState); + const stateForFolder = this.windowsState.openedWindows.filter(o => o.folderUri && isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState); if (stateForFolder.length) { return stateForFolder[0]; } diff --git a/src/vs/code/node/windowsFinder.ts b/src/vs/code/node/windowsFinder.ts index fa5fba59882..b69d3eec0db 100644 --- a/src/vs/code/node/windowsFinder.ts +++ b/src/vs/code/node/windowsFinder.ts @@ -10,7 +10,7 @@ import * as paths from 'vs/base/common/paths'; import { OpenContext } from 'vs/platform/windows/common/windows'; import { IWorkspaceIdentifier, IResolvedWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import URI from 'vs/base/common/uri'; -import { hasToIgnoreCase, isEqual, isEqualOrParent } from 'vs/base/common/resources'; +import { isEqual, isEqualOrParent } from 'vs/base/common/resources'; export interface ISimpleWindow { openedWorkspace?: IWorkspaceIdentifier; @@ -49,13 +49,13 @@ function findWindowOnFilePath(windows: W[], fileUri: UR for (let i = 0; i < workspaceWindows.length; i++) { const window = workspaceWindows[i]; const resolvedWorkspace = workspaceResolver(window.openedWorkspace); - if (resolvedWorkspace && resolvedWorkspace.folders.some(folder => isEqualOrParent(fileUri, folder.uri, hasToIgnoreCase(fileUri)))) { + if (resolvedWorkspace && resolvedWorkspace.folders.some(folder => isEqualOrParent(fileUri, folder.uri))) { return window; } } // Then go with single folder windows that are parent of the provided file path - const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && isEqualOrParent(fileUri, window.openedFolderUri, hasToIgnoreCase(fileUri))); + const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && isEqualOrParent(fileUri, window.openedFolderUri)); if (singleFolderWindowsOnFilePath.length) { return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderUri.path.length - b.openedFolderUri.path.length))[0]; } @@ -74,7 +74,7 @@ export function findWindowOnWorkspace(windows: W[], wor for (const window of windows) { // match on folder if (isSingleFolderWorkspaceIdentifier(workspace)) { - if (window.openedFolderUri && isEqual(window.openedFolderUri, workspace, hasToIgnoreCase(window.openedFolderUri))) { + if (window.openedFolderUri && isEqual(window.openedFolderUri, workspace)) { return window; } } @@ -111,7 +111,7 @@ export function findWindowOnWorkspaceOrFolderUri(window } // check for folder path - if (window.openedFolderUri && isEqual(window.openedFolderUri, uri, hasToIgnoreCase(uri))) { + if (window.openedFolderUri && isEqual(window.openedFolderUri, uri)) { return window; } } diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index 8c879b66d8b..278490fc6fe 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -121,7 +121,7 @@ export class BackupMainService implements IBackupMainService { } public registerFolderBackupSync(folderUri: URI): string { - if (!this.folderWorkspaces.some(uri => areResourcesEquals(folderUri, uri, hasToIgnoreCase(folderUri)))) { + if (!this.folderWorkspaces.some(uri => areResourcesEquals(folderUri, uri))) { this.folderWorkspaces.push(folderUri); this.saveSync(); } @@ -129,7 +129,7 @@ export class BackupMainService implements IBackupMainService { } public unregisterFolderBackupSync(folderUri: URI): void { - let index = arrays.firstIndex(this.folderWorkspaces, uri => areResourcesEquals(folderUri, uri, hasToIgnoreCase(folderUri))); + let index = arrays.firstIndex(this.folderWorkspaces, uri => areResourcesEquals(folderUri, uri)); if (index !== -1) { this.folderWorkspaces.splice(index, 1); this.saveSync(); diff --git a/src/vs/platform/history/electron-main/historyMainService.ts b/src/vs/platform/history/electron-main/historyMainService.ts index 3f2657d3851..84f4d3146e5 100644 --- a/src/vs/platform/history/electron-main/historyMainService.ts +++ b/src/vs/platform/history/electron-main/historyMainService.ts @@ -19,7 +19,7 @@ import { IHistoryMainService, IRecentlyOpened } from 'vs/platform/history/common import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { isEqual } from 'vs/base/common/paths'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { getComparisonKey, isEqual as areResourcesEqual, hasToIgnoreCase, dirname } from 'vs/base/common/resources'; +import { getComparisonKey, isEqual as areResourcesEqual, dirname } from 'vs/base/common/resources'; import URI, { UriComponents } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { IUriLabelService } from 'vs/platform/uriLabel/common/uriLabel'; @@ -129,11 +129,11 @@ export class HistoryMainService implements IHistoryMainService { return isWorkspaceIdentifier(workspace) && isEqual(pathToRemove.configPath, workspace.configPath, !isLinux /* ignorecase */); } if (isSingleFolderWorkspaceIdentifier(pathToRemove)) { - return isSingleFolderWorkspaceIdentifier(workspace) && areResourcesEqual(pathToRemove, workspace, hasToIgnoreCase(pathToRemove)); + return isSingleFolderWorkspaceIdentifier(workspace) && areResourcesEqual(pathToRemove, workspace); } if (typeof pathToRemove === 'string') { if (isSingleFolderWorkspaceIdentifier(workspace)) { - return workspace.scheme === Schemas.file && areResourcesEqual(URI.file(pathToRemove), workspace, hasToIgnoreCase(workspace)); + return workspace.scheme === Schemas.file && areResourcesEqual(URI.file(pathToRemove), workspace); } if (isWorkspaceIdentifier(workspace)) { return isEqual(pathToRemove, workspace.configPath, !isLinux /* ignorecase */); @@ -149,7 +149,7 @@ export class HistoryMainService implements IHistoryMainService { // Remove file const pathToRemoveURI = pathToRemove instanceof URI ? pathToRemove : typeof pathToRemove === 'string' ? URI.file(pathToRemove) : null; if (pathToRemoveURI) { - index = arrays.firstIndex(mru.files, file => areResourcesEqual(file, pathToRemoveURI, hasToIgnoreCase(pathToRemoveURI))); + index = arrays.firstIndex(mru.files, file => areResourcesEqual(file, pathToRemoveURI)); } if (index >= 0) { mru.files.splice(index, 1); diff --git a/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts index 0d8ad43f255..f99b69abbcc 100644 --- a/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/browser/editors/fileEditorTracker.ts @@ -148,7 +148,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut // Do NOT close any opened editor that matches the resource path (either equal or being parent) of the // resource we move to (movedTo). Otherwise we would close a resource that has been renamed to the same // path but different casing. - if (movedTo && resources.isEqualOrParent(resource, movedTo, resources.hasToIgnoreCase(resource))) { + if (movedTo && resources.isEqualOrParent(resource, movedTo)) { return; } @@ -156,7 +156,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut if (arg1 instanceof FileChangesEvent) { matches = arg1.contains(resource, FileChangeType.DELETED); } else { - matches = resources.isEqualOrParent(resource, arg1, resources.hasToIgnoreCase(resource)); + matches = resources.isEqualOrParent(resource, arg1); } if (!matches) { @@ -223,7 +223,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut const resource = editor.getResource(); // Update Editor if file (or any parent of the input) got renamed or moved - if (resources.isEqualOrParent(resource, oldResource, resources.hasToIgnoreCase(resource))) { + if (resources.isEqualOrParent(resource, oldResource)) { let reopenFileResource: URI; if (oldResource.toString() === resource.toString()) { reopenFileResource = newResource; // file got moved diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index 49d64d0a561..2b2127af5fc 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -157,7 +157,7 @@ export class ExplorerItem { // the folder is fully resolved if either it has a list of children or the client requested this by using the resolveTo // array of resource path to resolve. stat.isDirectoryResolved = !!raw.children || (!!resolveTo && resolveTo.some((r) => { - return resources.isEqualOrParent(r, stat.resource, resources.hasToIgnoreCase(r)); + return resources.isEqualOrParent(r, stat.resource); })); // Recurse into children diff --git a/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts index 8f6b4ca4793..d20ed821f30 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanelActions.ts @@ -36,7 +36,7 @@ import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IModelService } from 'vs/editor/common/services/modelService'; -import { isEqual, hasToIgnoreCase } from 'vs/base/common/resources'; +import { isEqual } from 'vs/base/common/resources'; export class ToggleMarkersPanelAction extends TogglePanelAction { @@ -297,7 +297,7 @@ export class QuickFixAction extends Action { this.update(); } else { modelService.onModelAdded(model => { - if (isEqual(model.uri, marker.resource, hasToIgnoreCase(model.uri))) { + if (isEqual(model.uri, marker.resource)) { this.update(); } }, this, this.disposables); diff --git a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts index 14494b0bdb3..88c1483e5b6 100644 --- a/src/vs/workbench/parts/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/parts/preferences/common/preferencesContribution.ts @@ -24,7 +24,7 @@ import { IEditorInput } from 'vs/workbench/common/editor'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { isLinux } from 'vs/base/common/platform'; -import { isEqual, hasToIgnoreCase } from 'vs/base/common/resources'; +import { isEqual } from 'vs/base/common/resources'; const schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); @@ -89,7 +89,7 @@ export class PreferencesContribution implements IWorkbenchContribution { const state = this.workspaceService.getWorkbenchState(); if (state === WorkbenchState.FOLDER) { const folders = this.workspaceService.getWorkspace().folders; - if (isEqual(resource, folders[0].toResource(FOLDER_SETTINGS_PATH), hasToIgnoreCase(resource))) { + if (isEqual(resource, folders[0].toResource(FOLDER_SETTINGS_PATH))) { return { override: this.preferencesService.openWorkspaceSettings(true, options, group) }; } } @@ -98,7 +98,7 @@ export class PreferencesContribution implements IWorkbenchContribution { else if (state === WorkbenchState.WORKSPACE) { const folders = this.workspaceService.getWorkspace().folders; for (let i = 0; i < folders.length; i++) { - if (isEqual(resource, folders[i].toResource(FOLDER_SETTINGS_PATH), hasToIgnoreCase(resource))) { + if (isEqual(resource, folders[i].toResource(FOLDER_SETTINGS_PATH))) { return { override: this.preferencesService.openFolderSettings(folders[i].uri, true, options, group) }; } } diff --git a/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts b/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts index abb914561cd..6ec87c8ce50 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/snippetsService.ts @@ -76,7 +76,7 @@ namespace schema { const extensionLocation = extension.description.extensionLocation; const snippetLocation = resources.joinPath(extensionLocation, snippet.path); - if (!resources.isEqualOrParent(snippetLocation, extensionLocation, resources.hasToIgnoreCase(snippetLocation))) { + if (!resources.isEqualOrParent(snippetLocation, extensionLocation)) { extension.collector.error(localize( 'invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 2df1c8ad96e..61a10f303f5 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -338,7 +338,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura return paths.normalize(relative(this.folderConfigurationPath.fsPath, resource.fsPath)); } } else { - if (resources.isEqualOrParent(resource, this.folderConfigurationPath, resources.hasToIgnoreCase(resource))) { + if (resources.isEqualOrParent(resource, this.folderConfigurationPath)) { return paths.normalize(relative(this.folderConfigurationPath.path, resource.path)); } } diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index df5c45ce917..eb73870a0be 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -40,7 +40,7 @@ import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/works import { UserConfiguration } from 'vs/platform/configuration/node/configuration'; import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { localize } from 'vs/nls'; -import { isEqual, hasToIgnoreCase } from 'vs/base/common/resources'; +import { isEqual } from 'vs/base/common/resources'; import { IUriLabelService } from 'vs/platform/uriLabel/common/uriLabel'; export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { @@ -133,7 +133,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { switch (this.getWorkbenchState()) { case WorkbenchState.FOLDER: - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && isEqual(workspaceIdentifier, this.workspace.folders[0].uri, hasToIgnoreCase(workspaceIdentifier)); + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && isEqual(workspaceIdentifier, this.workspace.folders[0].uri); case WorkbenchState.WORKSPACE: return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; } diff --git a/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts b/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts index 150400ab5c0..552888adf39 100644 --- a/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts +++ b/src/vs/workbench/services/jsonschemas/common/jsonValidationExtensionPoint.ts @@ -60,7 +60,7 @@ export class JSONValidationExtensionPoint { if (strings.startsWith(uri, './')) { try { const colorThemeLocation = resources.joinPath(extensionLocation, uri); - if (!resources.isEqualOrParent(colorThemeLocation, extensionLocation, resources.hasToIgnoreCase(colorThemeLocation))) { + if (!resources.isEqualOrParent(colorThemeLocation, extensionLocation)) { collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.url` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", configurationExtPoint.name, location, extensionLocation.path)); } } catch (e) { diff --git a/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts b/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts index cb08ce01cea..df7d609571b 100644 --- a/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts +++ b/src/vs/workbench/services/textMate/electron-browser/TMSyntax.ts @@ -313,7 +313,7 @@ export class TextMateService implements ITextMateService { } const grammarLocation = resources.joinPath(extensionLocation, syntax.path); - if (!resources.isEqualOrParent(grammarLocation, extensionLocation, resources.hasToIgnoreCase(grammarLocation))) { + if (!resources.isEqualOrParent(grammarLocation, extensionLocation)) { collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", grammarsExtPoint.name, grammarLocation.path, extensionLocation.path)); } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 6faef447dc3..bc21ebdd62e 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -33,7 +33,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { isLinux } from 'vs/base/common/platform'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; -import { isEqual, isEqualOrParent, hasToIgnoreCase } from 'vs/base/common/resources'; +import { isEqual, isEqualOrParent } from 'vs/base/common/resources'; /** * The text file editor model listens to changes to its underlying code editor model and saves these changes through the file service back to the disk. @@ -795,14 +795,14 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for snippets - if (isEqualOrParent(this.resource, URI.file(path.join(this.environmentService.appSettingsHome, 'snippets')), hasToIgnoreCase(this.resource))) { + if (isEqualOrParent(this.resource, URI.file(path.join(this.environmentService.appSettingsHome, 'snippets')))) { return 'snippets'; } // Check for workspace settings file const folders = this.contextService.getWorkspace().folders; for (let i = 0; i < folders.length; i++) { - if (isEqualOrParent(this.resource, folders[i].toResource('.vscode'), hasToIgnoreCase(this.resource))) { + if (isEqualOrParent(this.resource, folders[i].toResource('.vscode'))) { const filename = path.basename(this.resource.fsPath); if (TextFileEditorModel.WHITELIST_WORKSPACE_JSON.indexOf(filename) > -1) { return `.vscode/${filename}`; diff --git a/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts b/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts index de23498235b..202f8be0707 100644 --- a/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts +++ b/src/vs/workbench/services/themes/electron-browser/colorThemeStore.ts @@ -95,7 +95,7 @@ export class ColorThemeStore { } const colorThemeLocation = resources.joinPath(extensionLocation, theme.path); - if (!resources.isEqualOrParent(colorThemeLocation, extensionLocation, resources.hasToIgnoreCase(colorThemeLocation))) { + if (!resources.isEqualOrParent(colorThemeLocation, extensionLocation)) { collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", themesExtPoint.name, colorThemeLocation.path, extensionLocation.path)); } diff --git a/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts b/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts index 1cb58bb40f0..a16ed89c917 100644 --- a/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts +++ b/src/vs/workbench/services/themes/electron-browser/fileIconThemeStore.ts @@ -97,7 +97,7 @@ export class FileIconThemeStore { } const iconThemeLocation = resources.joinPath(extensionLocation, iconTheme.path); - if (!resources.isEqualOrParent(iconThemeLocation, extensionLocation, resources.hasToIgnoreCase(iconThemeLocation))) { + if (!resources.isEqualOrParent(iconThemeLocation, extensionLocation)) { collector.warn(nls.localize('invalid.path.1', "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.", iconThemeExtPoint.name, iconThemeLocation.path, extensionLocation.path)); } diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index 6caf2e400a4..3f31b7e7555 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -26,7 +26,7 @@ import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileS import { ICommandService } from 'vs/platform/commands/common/commands'; import { distinct } from 'vs/base/common/arrays'; import { isLinux } from 'vs/base/common/platform'; -import { isEqual, hasToIgnoreCase } from 'vs/base/common/resources'; +import { isEqual } from 'vs/base/common/resources'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; export class WorkspaceEditingService implements IWorkspaceEditingService { @@ -138,7 +138,7 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { private includesSingleFolderWorkspace(folders: URI[]): boolean { if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { const workspaceFolder = this.contextService.getWorkspace().folders[0]; - return (folders.some(folder => isEqual(folder, workspaceFolder.uri, hasToIgnoreCase(folder)))); + return (folders.some(folder => isEqual(folder, workspaceFolder.uri))); } return false; diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index c0970077503..28b58ffa681 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -150,7 +150,7 @@ export class TestContextService implements IWorkspaceContextService { public isInsideWorkspace(resource: URI): boolean { if (resource && this.workspace) { - return resources.isEqualOrParent(resource, this.workspace.folders[0].uri, resources.hasToIgnoreCase(resource)); + return resources.isEqualOrParent(resource, this.workspace.folders[0].uri); } return false; @@ -161,7 +161,7 @@ export class TestContextService implements IWorkspaceContextService { } public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && resources.isEqual(this.workspace.folders[0].uri, workspaceIdentifier, resources.hasToIgnoreCase(workspaceIdentifier)); + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && resources.isEqual(this.workspace.folders[0].uri, workspaceIdentifier); } } From 669f2c8627741d4c48e199642b72dfa702c7f3d4 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 12:18:30 +0200 Subject: [PATCH 10/44] use vscode-nls-dev-loader --- extensions/git/extension.webpack.config.js | 6 +-- extensions/shared.webpack.config.js | 49 ++++++++++------------ package.json | 2 +- yarn.lock | 6 +-- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/extensions/git/extension.webpack.config.js b/extensions/git/extension.webpack.config.js index 743109f4343..75643a14039 100644 --- a/extensions/git/extension.webpack.config.js +++ b/extensions/git/extension.webpack.config.js @@ -13,8 +13,8 @@ const myConfig = { __dirname: false // leave the __dirname-behaviour intact }, entry: { - main: './out/main.js', - ['askpass-main']: './out/askpass-main.js' + main: './src/main.ts', + ['askpass-main']: './src/askpass-main.ts' }, plugins: [ new CopyWebpackPlugin([ @@ -34,4 +34,4 @@ const myConfig = { }, }; -module.exports = { ...sharedConfig(__dirname, false), ...myConfig }; +module.exports = { ...sharedConfig(__dirname), ...myConfig }; diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index 12ccb0c39dc..bbb8e580f7e 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -12,17 +12,36 @@ const path = require('path'); * returns a good default configuation for extensions that * want to do webpack */ -module.exports = function (extensionDir, useTsLoader = true) { - let config = { +module.exports = function (extensionDir) { + return { context: extensionDir, mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') target: 'node', // extensions run in a node context resolve: { mainFields: ['main'], // prefer the main-entry of package.json files - extensions: [".js"] + extensions: ['.ts', '.js'] // support ts-files and js-files }, module: { - rules: [] + rules: [{ + test: /\.ts$/, + exclude: /node_modules/, + use: [{ + // vscode-nls-dev loader: + // * rewrite nls-calls + loader: 'vscode-nls-dev/lib/webpack-loader' + }, { + // configure TypeScript loader: + // * only transpile because we have a separate compilation pipeline + // * enable sources maps for end-to-end source maps + loader: 'ts-loader', + options: { + transpileOnly: true, + compilerOptions: { + "sourceMap": true, + } + } + }] + }] }, output: { // all output goes into `dist`. @@ -34,26 +53,4 @@ module.exports = function (extensionDir, useTsLoader = true) { // yes, really source maps devtool: 'source-map' }; - - if (useTsLoader) { - config.resolve.extensions = [".ts", ".js"]; // support ts-files and js-files - config.module.rules = [{ - // configure TypeScript loader: - // * only transpile because we have a separate compilation pipeline - // * enable sources maps for end-to-end source maps - test: /\.ts$/, - exclude: /node_modules/, - use: [{ - loader: 'ts-loader', - options: { - transpileOnly: true, - compilerOptions: { - "sourceMap": true, - } - } - }] - }]; - } - - return config; }; diff --git a/package.json b/package.json index 5b73450aa47..0564808a470 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "vinyl": "^0.4.5", "vinyl-fs": "^2.4.3", "vsce": "1.33.2", - "vscode-nls-dev": "3.1.1", + "vscode-nls-dev": "3.2.0", "webpack": "^4.16.5", "webpack-cli": "^3.1.0", "webpack-stream": "^5.1.1" diff --git a/yarn.lock b/yarn.lock index e67580f77c1..49c567af992 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7880,9 +7880,9 @@ vscode-fsevents@0.3.8: dependencies: nan "^2.3.0" -vscode-nls-dev@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.1.1.tgz#e7fa2e8e641b1579b25779acfda0e5f7c28f1fb9" +vscode-nls-dev@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.2.0.tgz#c4fe3977393b2785b82a7f0ccb2e47fd547c8657" dependencies: clone "^2.1.1" event-stream "^3.3.4" From 7661d6f9d40e1f037430c709ba63d43e2b4f9dc8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 12:29:13 +0200 Subject: [PATCH 11/44] remove webpack knowlegde from gulpfile.extensions --- build/gulpfile.extensions.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index bedc9a293fb..bd38427a422 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -8,7 +8,6 @@ require('events').EventEmitter.defaultMaxListeners = 100; const gulp = require('gulp'); const path = require('path'); -const fs = require('fs'); const tsb = require('gulp-tsb'); const es = require('event-stream'); const filter = require('gulp-filter'); @@ -75,7 +74,6 @@ const tasks = compilations.map(function (tsconfigFile) { tsOptions.base = path.dirname(absolutePath); const compilation = tsb.create(tsOptions, null, null, err => reporter(err.toString())); - const nlsOption = fs.existsSync(path.join(root, 'extension.webpack.config.js')) ? { keepFilenames: true } : undefined; return function () { const input = es.through(); @@ -91,7 +89,7 @@ const tasks = compilations.map(function (tsconfigFile) { .pipe(tsFilter) .pipe(util.loadSourcemaps()) .pipe(compilation()) - .pipe(build ? nlsDev.rewriteLocalizeCalls(nlsOption) : es.through()) + .pipe(build ? nlsDev.rewriteLocalizeCalls() : es.through()) .pipe(build ? util.stripSourceMappingURL() : es.through()) .pipe(sourcemaps.write('.', { sourceMappingURL: !build ? null : f => `${baseUrl}/${f.relative}.map`, From bc05425af67e5481999db4a092ce716572501db6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 12:46:34 +0200 Subject: [PATCH 12/44] one more update... --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0564808a470..864d2fa74c6 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "vinyl": "^0.4.5", "vinyl-fs": "^2.4.3", "vsce": "1.33.2", - "vscode-nls-dev": "3.2.0", + "vscode-nls-dev": "3.2.1", "webpack": "^4.16.5", "webpack-cli": "^3.1.0", "webpack-stream": "^5.1.1" diff --git a/yarn.lock b/yarn.lock index 49c567af992..071f2d8c7c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7880,9 +7880,9 @@ vscode-fsevents@0.3.8: dependencies: nan "^2.3.0" -vscode-nls-dev@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.2.0.tgz#c4fe3977393b2785b82a7f0ccb2e47fd547c8657" +vscode-nls-dev@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.2.1.tgz#8aa9537b67d1e6e7ea4c6c4f80043c46c8a725ea" dependencies: clone "^2.1.1" event-stream "^3.3.4" From 7b5dc58be23808a478f3c7b09e7dd2b527091745 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 13:59:06 +0200 Subject: [PATCH 13/44] debug: cleanup EH debugging --- .../debug/electron-browser/debugService.ts | 27 +++++++------------ .../debug/electron-browser/debugSession.ts | 8 +++--- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index a360dabf1cc..4c2c1026a84 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -143,20 +143,10 @@ export class DebugService implements IDebugService { } if (broadcast.channel === EXTENSION_ATTACH_BROADCAST_CHANNEL) { - const initialAttach = session.configuration.request === 'launch'; - session.configuration.request = 'attach'; session.configuration.port = broadcast.payload.port; - // Do not end process on initial attach (since the request is still 'launch') - if (initialAttach) { - const dbgr = this.configurationManager.getDebugger(session.configuration.type); - session.initialize(dbgr).then(() => (session.raw).attach(session.configuration)); - } else { - if (session.raw) { - session.raw.disconnect().done(undefined, errors.onUnexpectedError); - } - this.doCreateSession(session.root, { resolved: session.configuration, unresolved: session.unresolvedConfiguration }, session.getId()); - } + const dbgr = this.configurationManager.getDebugger(session.configuration.type); + session.initialize(dbgr).then(() => (session.raw).attach(session.configuration)); return; } @@ -914,14 +904,15 @@ export class DebugService implements IDebugService { // Do not run preLaunch and postDebug tasks for automatic restarts this.skipRunningTask = !!restartData; + if (equalsIgnoreCase(session.configuration.type, 'extensionHost') && session.root) { + return this.broadcastService.broadcast({ + channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, + payload: [session.root.uri.fsPath] + }); + } + // If the restart is automatic disconnect, otherwise send the terminate signal #55064 return (!!restartData ? session.raw.disconnect(true) : session.raw.terminate(true)).then(() => { - if (equalsIgnoreCase(session.configuration.type, 'extensionHost') && session.root) { - return this.broadcastService.broadcast({ - channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, - payload: [session.root.uri.fsPath] - }); - } return new TPromise((c, e) => { setTimeout(() => { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts index 1be9dbc2494..b80961dab3a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts @@ -225,11 +225,11 @@ export class Session implements ISession { } initialize(dbgr: Debugger): TPromise { + if (this._raw) { + // If there was already a connection make sure to remove old listeners + this.rawListeners = dispose(this.rawListeners); + } return dbgr.getCustomTelemetryService().then(customTelemetryService => { - if (this._raw) { - // If there was already a connection make sure to remove old listeners - dispose(this.rawListeners); - } this._raw = this.instantiationService.createInstance(RawDebugSession, this.id, this._configuration.resolved.debugServer, dbgr, customTelemetryService, this.root); this.registerListeners(); From 01365dbe260a751dc4baf8a18b8bdd514a79229e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 15:23:56 +0200 Subject: [PATCH 14/44] webpack - more defaults for extensions --- extensions/emmet/extension.webpack.config.js | 6 +- extensions/git/extension.webpack.config.js | 9 +-- extensions/shared.webpack.config.js | 79 +++++++++++++++++--- package.json | 1 + yarn.lock | 8 +- 5 files changed, 83 insertions(+), 20 deletions(-) diff --git a/extensions/emmet/extension.webpack.config.js b/extensions/emmet/extension.webpack.config.js index 55b15a2701a..b86756e4aa8 100644 --- a/extensions/emmet/extension.webpack.config.js +++ b/extensions/emmet/extension.webpack.config.js @@ -5,14 +5,14 @@ 'use strict'; -const sharedConfig = require('../shared.webpack.config'); +const withDefaults = require('../shared.webpack.config'); const myConfig = { + context: __dirname, entry: { extension: './src/extension.ts', }, externals: { - 'vscode': 'commonjs vscode', // ignored because it doesn't exist '@emmetio/css-parser': 'commonjs @emmetio/css-parser', '@emmetio/html-matcher': 'commonjs @emmetio/html-matcher', '@emmetio/math-expression': 'commonjs @emmetio/math-expression', @@ -21,4 +21,4 @@ const myConfig = { }, }; -module.exports = { ...sharedConfig(__dirname), ...myConfig }; +module.exports = withDefaults(myConfig); diff --git a/extensions/git/extension.webpack.config.js b/extensions/git/extension.webpack.config.js index 75643a14039..44e0d7dff17 100644 --- a/extensions/git/extension.webpack.config.js +++ b/extensions/git/extension.webpack.config.js @@ -5,10 +5,11 @@ 'use strict'; -const sharedConfig = require('../shared.webpack.config'); +const withDefaults = require('../shared.webpack.config'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const myConfig = { + context: __dirname, node: { __dirname: false // leave the __dirname-behaviour intact }, @@ -18,12 +19,10 @@ const myConfig = { }, plugins: [ new CopyWebpackPlugin([ - { from: './out/*.sh', to: '[name].sh' }, - { from: './out/nls.*.json', to: '[name].json' } + { from: './out/*.sh', to: '[name].sh' } ]) ], externals: { - 'vscode': 'commonjs vscode', // ignored because it doesn't exist "byline": 'commonjs byline', "file-type": 'commonjs file-type', "iconv-lite": 'commonjs iconv-lite', @@ -34,4 +33,4 @@ const myConfig = { }, }; -module.exports = { ...sharedConfig(__dirname), ...myConfig }; +module.exports = withDefaults(myConfig); diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index bbb8e580f7e..7195a844fc8 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -6,15 +6,11 @@ 'use strict'; const path = require('path'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const merge = require('merge-options'); -/** - * Function that must be invoked with __dirname and that - * returns a good default configuation for extensions that - * want to do webpack - */ -module.exports = function (extensionDir) { - return { - context: extensionDir, +module.exports = function withDefaults(extConfig) { + let defaultConfig = { mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') target: 'node', // extensions run in a node context resolve: { @@ -43,14 +39,75 @@ module.exports = function (extensionDir) { }] }] }, + plugins: [ + new CopyWebpackPlugin([{ from: './out/nls.*.json', to: '[name].json' }]) // copy nls files + ], + externals: { + 'vscode': 'commonjs vscode', // ignored because it doesn't exist + }, output: { // all output goes into `dist`. // packaging depends on that and this must always be like it filename: '[name].js', - path: path.join(extensionDir, 'dist'), + path: path.join(extConfig.context, 'dist'), libraryTarget: "commonjs", }, // yes, really source maps devtool: 'source-map' - }; -}; + } + + return merge(defaultConfig, extConfig); +} + +// /** +// * Function that must be invoked with __dirname and that +// * returns a good default configuation for extensions that +// * want to do webpack +// */ +// module.exports = function (extensionDir) { +// return { +// context: extensionDir, +// mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') +// target: 'node', // extensions run in a node context +// resolve: { +// mainFields: ['main'], // prefer the main-entry of package.json files +// extensions: ['.ts', '.js'] // support ts-files and js-files +// }, +// module: { +// rules: [{ +// test: /\.ts$/, +// exclude: /node_modules/, +// use: [{ +// // vscode-nls-dev loader: +// // * rewrite nls-calls +// loader: 'vscode-nls-dev/lib/webpack-loader' +// }, { +// // configure TypeScript loader: +// // * only transpile because we have a separate compilation pipeline +// // * enable sources maps for end-to-end source maps +// loader: 'ts-loader', +// options: { +// transpileOnly: true, +// compilerOptions: { +// "sourceMap": true, +// } +// } +// }] +// }] +// }, +// plugins: [ +// new CopyWebpackPlugin([ +// { from: './out/nls.*.json', to: '[name].json' } +// ]) +// ], +// output: { +// // all output goes into `dist`. +// // packaging depends on that and this must always be like it +// filename: '[name].js', +// path: path.join(extensionDir, 'dist'), +// libraryTarget: "commonjs", +// }, +// // yes, really source maps +// devtool: 'source-map' +// }; +// }; diff --git a/package.json b/package.json index 864d2fa74c6..136b3a54767 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "istanbul": "^0.3.17", "jsdom-no-contextify": "^3.1.0", "lazy.js": "^0.4.2", + "merge-options": "^1.0.1", "mime": "^1.4.1", "minimatch": "^2.0.10", "mkdirp": "^0.5.0", diff --git a/yarn.lock b/yarn.lock index 071f2d8c7c9..a791e42fb98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3909,7 +3909,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -4724,6 +4724,12 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" + dependencies: + is-plain-obj "^1.1" + merge-stream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" From 4bf5813f7962f0fa488901dfa793386fec3dd871 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 15:29:54 +0200 Subject: [PATCH 15/44] :lipstick: --- extensions/shared.webpack.config.js | 53 ----------------------------- 1 file changed, 53 deletions(-) diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index 7195a844fc8..b98d911ce80 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -58,56 +58,3 @@ module.exports = function withDefaults(extConfig) { return merge(defaultConfig, extConfig); } - -// /** -// * Function that must be invoked with __dirname and that -// * returns a good default configuation for extensions that -// * want to do webpack -// */ -// module.exports = function (extensionDir) { -// return { -// context: extensionDir, -// mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') -// target: 'node', // extensions run in a node context -// resolve: { -// mainFields: ['main'], // prefer the main-entry of package.json files -// extensions: ['.ts', '.js'] // support ts-files and js-files -// }, -// module: { -// rules: [{ -// test: /\.ts$/, -// exclude: /node_modules/, -// use: [{ -// // vscode-nls-dev loader: -// // * rewrite nls-calls -// loader: 'vscode-nls-dev/lib/webpack-loader' -// }, { -// // configure TypeScript loader: -// // * only transpile because we have a separate compilation pipeline -// // * enable sources maps for end-to-end source maps -// loader: 'ts-loader', -// options: { -// transpileOnly: true, -// compilerOptions: { -// "sourceMap": true, -// } -// } -// }] -// }] -// }, -// plugins: [ -// new CopyWebpackPlugin([ -// { from: './out/nls.*.json', to: '[name].json' } -// ]) -// ], -// output: { -// // all output goes into `dist`. -// // packaging depends on that and this must always be like it -// filename: '[name].js', -// path: path.join(extensionDir, 'dist'), -// libraryTarget: "commonjs", -// }, -// // yes, really source maps -// devtool: 'source-map' -// }; -// }; From 66205890dd3cb6b4f2c42bb662bdd372c3dad9df Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 15:31:33 +0200 Subject: [PATCH 16/44] Revert "Revert "remove proposed Logger-api, #43275"" This reverts commit 315cce8314801ba9b25190682fad7fb48e797a9f. --- src/vs/vscode.proposed.d.ts | 16 ------ src/vs/workbench/api/node/extHost.api.impl.ts | 5 +- .../api/node/extHostExtensionActivator.ts | 2 - .../api/node/extHostExtensionService.ts | 4 -- .../workbench/api/node/extHostLogService.ts | 50 ------------------- 5 files changed, 4 insertions(+), 73 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 3de4a7af9dd..7c10f6b6b56 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -434,23 +434,7 @@ declare module 'vscode' { Off = 7 } - /** - * A logger for writing to an extension's log file, and accessing its dedicated log directory. - */ - export interface Logger { - trace(message: string, ...args: any[]): void; - debug(message: string, ...args: any[]): void; - info(message: string, ...args: any[]): void; - warn(message: string, ...args: any[]): void; - error(message: string | Error, ...args: any[]): void; - critical(message: string | Error, ...args: any[]): void; - } - export interface ExtensionContext { - /** - * This extension's logger - */ - logger: Logger; /** * Path where an extension can write log files. diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index ea64898c5b1..a8afbaabb36 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -227,7 +227,10 @@ export function createApiFactory( get language() { return platform.language; }, get appName() { return product.nameLong; }, get appRoot() { return initData.environment.appRoot; }, - get logLevel() { return extHostLogService.getLevel(); } + get logLevel() { + checkProposedApiEnabled(extension); + return extHostLogService.getLevel(); + } }); // namespace: extensions diff --git a/src/vs/workbench/api/node/extHostExtensionActivator.ts b/src/vs/workbench/api/node/extHostExtensionActivator.ts index cbd8a70d649..b392d0182f1 100644 --- a/src/vs/workbench/api/node/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/node/extHostExtensionActivator.ts @@ -10,7 +10,6 @@ import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { ExtHostLogger } from 'vs/workbench/api/node/extHostLogService'; const hasOwnProperty = Object.hasOwnProperty; const NO_OP_VOID_PROMISE = TPromise.wrap(void 0); @@ -27,7 +26,6 @@ export interface IExtensionContext { extensionPath: string; storagePath: string; asAbsolutePath(relativePath: string): string; - logger: ExtHostLogger; readonly logDirectory: string; readonly logPath: string; } diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index f29e288412b..06c52263022 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -361,10 +361,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { get extensionPath() { return extensionDescription.extensionLocation.fsPath; }, storagePath: this._storagePath.value(extensionDescription), asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionLocation.fsPath, relativePath); }, - get logger() { - checkProposedApiEnabled(extensionDescription); - return that._extHostLogService.getExtLogger(extensionDescription.id); - }, get logDirectory() { console.warn(`this PROPOSED API has been RENAMED to 'logPath'`); checkProposedApiEnabled(extensionDescription); diff --git a/src/vs/workbench/api/node/extHostLogService.ts b/src/vs/workbench/api/node/extHostLogService.ts index 6708690a2f4..31b0113188f 100644 --- a/src/vs/workbench/api/node/extHostLogService.ts +++ b/src/vs/workbench/api/node/extHostLogService.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as vscode from 'vscode'; import { join } from 'vs/base/common/paths'; import { LogLevel } from 'vs/workbench/api/node/extHostTypes'; import { ILogService, DelegatedLogService } from 'vs/platform/log/common/log'; @@ -14,8 +13,6 @@ import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol'; export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape { - private _loggers: Map = new Map(); - constructor( private _windowId: number, logLevel: LogLevel, @@ -28,54 +25,7 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic this.setLevel(level); } - getExtLogger(extensionID: string): ExtHostLogger { - let logger = this._loggers.get(extensionID); - if (!logger) { - logger = this.createLogger(extensionID); - this._loggers.set(extensionID, logger); - } - return logger; - } - getLogDirectory(extensionID: string): string { return join(this._logsPath, `${extensionID}_${this._windowId}`); } - - private createLogger(extensionID: string): ExtHostLogger { - const logsDirPath = this.getLogDirectory(extensionID); - const logService = createSpdLogService(extensionID, this.getLevel(), logsDirPath); - this._register(this.onDidChangeLogLevel(level => logService.setLevel(level))); - return new ExtHostLogger(logService); - } -} - -export class ExtHostLogger implements vscode.Logger { - - constructor( - private readonly _logService: ILogService - ) { } - - trace(message: string, ...args: any[]): void { - return this._logService.trace(message, ...args); - } - - debug(message: string, ...args: any[]): void { - return this._logService.debug(message, ...args); - } - - info(message: string, ...args: any[]): void { - return this._logService.info(message, ...args); - } - - warn(message: string, ...args: any[]): void { - return this._logService.warn(message, ...args); - } - - error(message: string | Error, ...args: any[]): void { - return this._logService.error(message, ...args); - } - - critical(message: string | Error, ...args: any[]): void { - return this._logService.critical(message, ...args); - } } From 27c72d4ea482398c69010276c1a21276a653287e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 15:42:09 +0200 Subject: [PATCH 17/44] remove logDirectory, #43275 --- .../src/utils/logDirectoryProvider.ts | 6 +++--- src/vs/vscode.proposed.d.ts | 10 ---------- src/vs/workbench/api/node/extHostExtensionActivator.ts | 1 - src/vs/workbench/api/node/extHostExtensionService.ts | 7 +------ 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/extensions/typescript-language-features/src/utils/logDirectoryProvider.ts b/extensions/typescript-language-features/src/utils/logDirectoryProvider.ts index fba55ea03e1..5f97d445a90 100644 --- a/extensions/typescript-language-features/src/utils/logDirectoryProvider.ts +++ b/extensions/typescript-language-features/src/utils/logDirectoryProvider.ts @@ -28,13 +28,13 @@ export default class LogDirectoryProvider { @memoize private logDirectory(): string | undefined { try { - const path = this.context.logDirectory; + const path = this.context.logPath; if (!fs.existsSync(path)) { fs.mkdirSync(path); } - return this.context.logDirectory; + return this.context.logPath; } catch { return undefined; } } -} \ No newline at end of file +} diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 7c10f6b6b56..9b3a074851d 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -434,16 +434,6 @@ declare module 'vscode' { Off = 7 } - export interface ExtensionContext { - - /** - * Path where an extension can write log files. - * - * Extensions must create this directory before writing to it. The parent directory will always exist. - */ - readonly logDirectory: string; - } - export namespace env { /** * Current logging level. diff --git a/src/vs/workbench/api/node/extHostExtensionActivator.ts b/src/vs/workbench/api/node/extHostExtensionActivator.ts index b392d0182f1..5218f66cda6 100644 --- a/src/vs/workbench/api/node/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/node/extHostExtensionActivator.ts @@ -26,7 +26,6 @@ export interface IExtensionContext { extensionPath: string; storagePath: string; asAbsolutePath(relativePath: string): string; - readonly logDirectory: string; readonly logPath: string; } diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 06c52263022..2fe2cf9cd2e 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -12,7 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage'; -import { createApiFactory, initializeExtensionApi, checkProposedApiEnabled } from 'vs/workbench/api/node/extHost.api.impl'; +import { createApiFactory, initializeExtensionApi } from 'vs/workbench/api/node/extHost.api.impl'; import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape, IMainContext } from './extHost.protocol'; import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes, ExtensionActivationReason, ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; @@ -361,11 +361,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { get extensionPath() { return extensionDescription.extensionLocation.fsPath; }, storagePath: this._storagePath.value(extensionDescription), asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionLocation.fsPath, relativePath); }, - get logDirectory() { - console.warn(`this PROPOSED API has been RENAMED to 'logPath'`); - checkProposedApiEnabled(extensionDescription); - return that._extHostLogService.getLogDirectory(extensionDescription.id); - }, logPath: that._extHostLogService.getLogDirectory(extensionDescription.id) }); }); From ebe2979d0c05a2914132106d2f4ea6aabcfe301f Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 15:47:06 +0200 Subject: [PATCH 18/44] debugService: run task return a success boolean --- .../debug/electron-browser/debugService.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 4c2c1026a84..6499553b46c 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -606,9 +606,13 @@ export class DebugService implements IDebugService { } const workspace = launch ? launch.workspace : undefined; - return this.runTask(sessionId, workspace, resolvedConfig.preLaunchTask, resolvedConfig, unresolvedConfig, - () => this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, sessionId) - ); + return this.runTask(sessionId, workspace, resolvedConfig.preLaunchTask, resolvedConfig, unresolvedConfig).then(success => { + if (!success) { + return undefined; + } + + return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, sessionId); + }); }, err => { if (err && err.message) { return this.showError(err.message); @@ -798,7 +802,7 @@ export class DebugService implements IDebugService { }); } - private runTask(sessionId: string, root: IWorkspaceFolder, taskId: string | TaskIdentifier, config: IConfig, unresolvedConfig: IConfig, onSuccess: () => TPromise): TPromise { + private runTask(sessionId: string, root: IWorkspaceFolder, taskId: string | TaskIdentifier, config: IConfig, unresolvedConfig: IConfig): TPromise { const debugAnywayAction = new Action('debug.debugAnyway', nls.localize('debugAnyway', "Debug Anyway"), undefined, true, () => { return this.doCreateSession(root, { resolved: config, unresolved: unresolvedConfig }, sessionId); }); @@ -808,7 +812,7 @@ export class DebugService implements IDebugService { const successExitCode = taskSummary && taskSummary.exitCode === 0; const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; if (successExitCode || (errorCount === 0 && !failureExitCode)) { - return onSuccess(); + return true; } const message = errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", config.preLaunchTask) : @@ -819,9 +823,9 @@ export class DebugService implements IDebugService { return this.panelService.openPanel(Constants.MARKERS_PANEL_ID).then(() => undefined); }); - return this.showError(message, [debugAnywayAction, showErrorsAction]); + return this.showError(message, [debugAnywayAction, showErrorsAction]).then(() => false); }, (err: TaskError) => { - return this.showError(err.message, [debugAnywayAction, this.taskService.configureAction()]); + return this.showError(err.message, [debugAnywayAction, this.taskService.configureAction()]).then(() => false); }); } @@ -894,9 +898,9 @@ export class DebugService implements IDebugService { return this.textFileService.saveAll().then(() => { const unresolvedConfiguration = (session).unresolvedConfiguration; if (session.raw.capabilities.supportsRestartRequest) { - return this.runTask(session.getId(), session.root, session.configuration.postDebugTask, session.configuration, unresolvedConfiguration, - () => this.runTask(session.getId(), session.root, session.configuration.preLaunchTask, session.configuration, unresolvedConfiguration, - () => session.raw.custom('restart', null))); + return this.runTask(session.getId(), session.root, session.configuration.postDebugTask, session.configuration, unresolvedConfiguration) + .then(success => success ? this.runTask(session.getId(), session.root, session.configuration.preLaunchTask, session.configuration, unresolvedConfiguration) + .then(success => success ? session.raw.custom('restart', null) : undefined) : TPromise.as(undefined)); } const focusedSession = this.viewModel.focusedSession; From 287d9621225ced66b72e695af77f3715977f9301 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 20 Aug 2018 12:11:37 +0200 Subject: [PATCH 19/44] Fix potential npe on code actions #56501 --- src/vs/editor/contrib/codeAction/codeActionWidget.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/codeAction/codeActionWidget.ts b/src/vs/editor/contrib/codeAction/codeActionWidget.ts index b680ed6008b..ebf9f659b0f 100644 --- a/src/vs/editor/contrib/codeAction/codeActionWidget.ts +++ b/src/vs/editor/contrib/codeAction/codeActionWidget.ts @@ -30,7 +30,7 @@ export class CodeActionContextMenu { show(fixes: Thenable, at: { x: number; y: number } | Position) { - const actions = fixes.then(value => { + const actions = fixes ? fixes.then(value => { return value.map(action => { return new Action(action.command ? action.command.id : action.title, action.title, undefined, true, () => { return always( @@ -41,10 +41,10 @@ export class CodeActionContextMenu { }).then(actions => { if (!this._editor.getDomNode()) { // cancel when editor went off-dom - return TPromise.wrapError(canceled()); + return TPromise.wrapError(canceled()); } return actions; - }); + }) : TPromise.as([] as Action[]); this._contextMenuService.showContextMenu({ getAnchor: () => { From d039671ad1d0ec35695be60b7ddbe95f73ceb117 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 20 Aug 2018 12:11:46 +0200 Subject: [PATCH 20/44] Update js/ts grammars --- .../syntaxes/JavaScript.tmLanguage.json | 193 ++++++++++-------- .../syntaxes/JavaScriptReact.tmLanguage.json | 193 ++++++++++-------- .../syntaxes/TypeScript.tmLanguage.json | 193 ++++++++++-------- .../syntaxes/TypeScriptReact.tmLanguage.json | 193 ++++++++++-------- 4 files changed, 448 insertions(+), 324 deletions(-) diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 2b6ae46fe6d..c22cec229fa 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/858d33f03943e4ec040e81cbabbc3f7892157c18", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/d33674e802be357bff20cf8b0a4c966be54c39c4", "name": "JavaScript (with React support)", "scopeName": "source.js", "patterns": [ @@ -93,6 +93,10 @@ }, { "include": "#export-declaration" + }, + { + "name": "storage.modifier.js", + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "captures": { + "1": { + "name": "meta.definition.property.js entity.name.function.js" }, - { - "include": "#string" - }, - { - "include": "#array-literal" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#comment" - }, - { - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\?)?(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "meta.definition.property.js entity.name.function.js" - }, - "2": { - "name": "keyword.operator.optional.js" - } - } - }, - { - "name": "meta.definition.property.js variable.object.property.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js", - "match": "\\?" + "2": { + "name": "keyword.operator.optional.js" } - ] + } + }, + { + "name": "meta.definition.property.js variable.object.property.js", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.js", + "match": "\\?" } ] }, @@ -1107,21 +1113,24 @@ }, "function-declaration": { "name": "meta.function.js", - "begin": "(?\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3495,6 +3528,10 @@ }, { "include": "#punctuation-comma" + }, + { + "name": "keyword.operator.assignment.js", + "match": "(=)(?!>)" } ] }, @@ -3863,13 +3900,10 @@ "include": "#typeof-operator" }, { - "begin": "(?:([&|])|(=(?!>)))(?=\\s*\\{)", + "begin": "([&|\\*])(?=\\s*\\{)", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.js" - }, - "2": { - "name": "keyword.operator.assignment.js" } }, "end": "(?<=\\})", @@ -3880,13 +3914,10 @@ ] }, { - "begin": "([&|])|(=(?!>))", + "begin": "[&|\\*]", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.js" - }, - "2": { - "name": "keyword.operator.assignment.js" } }, "end": "(?=\\S)" @@ -4018,7 +4049,7 @@ "patterns": [ { "name": "string.template.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", "beginCaptures": { "1": { "name": "entity.name.function.tagged-template.js" diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index 15eeb04d7fc..5da9fb79ada 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/858d33f03943e4ec040e81cbabbc3f7892157c18", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/d33674e802be357bff20cf8b0a4c966be54c39c4", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "patterns": [ @@ -93,6 +93,10 @@ }, { "include": "#export-declaration" + }, + { + "name": "storage.modifier.js.jsx", + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "captures": { + "1": { + "name": "meta.definition.property.js.jsx entity.name.function.js.jsx" }, - { - "include": "#string" - }, - { - "include": "#array-literal" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#comment" - }, - { - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\?)?(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "meta.definition.property.js.jsx entity.name.function.js.jsx" - }, - "2": { - "name": "keyword.operator.optional.js.jsx" - } - } - }, - { - "name": "meta.definition.property.js.jsx variable.object.property.js.jsx", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js.jsx", - "match": "\\?" + "2": { + "name": "keyword.operator.optional.js.jsx" } - ] + } + }, + { + "name": "meta.definition.property.js.jsx variable.object.property.js.jsx", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.js.jsx", + "match": "\\?" } ] }, @@ -1107,21 +1113,24 @@ }, "function-declaration": { "name": "meta.function.js.jsx", - "begin": "(?\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js.jsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3495,6 +3528,10 @@ }, { "include": "#punctuation-comma" + }, + { + "name": "keyword.operator.assignment.js.jsx", + "match": "(=)(?!>)" } ] }, @@ -3863,13 +3900,10 @@ "include": "#typeof-operator" }, { - "begin": "(?:([&|])|(=(?!>)))(?=\\s*\\{)", + "begin": "([&|\\*])(?=\\s*\\{)", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.js.jsx" - }, - "2": { - "name": "keyword.operator.assignment.js.jsx" } }, "end": "(?<=\\})", @@ -3880,13 +3914,10 @@ ] }, { - "begin": "([&|])|(=(?!>))", + "begin": "[&|\\*]", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.js.jsx" - }, - "2": { - "name": "keyword.operator.assignment.js.jsx" } }, "end": "(?=\\S)" @@ -4018,7 +4049,7 @@ "patterns": [ { "name": "string.template.js.jsx", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", "beginCaptures": { "1": { "name": "entity.name.function.tagged-template.js.jsx" diff --git a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json index 6f5bc2d554d..9b62ccbf2a7 100644 --- a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/858d33f03943e4ec040e81cbabbc3f7892157c18", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/d33674e802be357bff20cf8b0a4c966be54c39c4", "name": "TypeScript", "scopeName": "source.ts", "patterns": [ @@ -93,6 +93,10 @@ }, { "include": "#export-declaration" + }, + { + "name": "storage.modifier.ts", + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "captures": { + "1": { + "name": "meta.definition.property.ts entity.name.function.ts" }, - { - "include": "#string" - }, - { - "include": "#array-literal" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#comment" - }, - { - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\?)?(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|((<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?[\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "meta.definition.property.ts entity.name.function.ts" - }, - "2": { - "name": "keyword.operator.optional.ts" - } - } - }, - { - "name": "meta.definition.property.ts variable.object.property.ts", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.ts", - "match": "\\?" + "2": { + "name": "keyword.operator.optional.ts" } - ] + } + }, + { + "name": "meta.definition.property.ts variable.object.property.ts", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.ts", + "match": "\\?" } ] }, @@ -1104,21 +1110,24 @@ }, "function-declaration": { "name": "meta.function.ts", - "begin": "(?\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.ts", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3529,6 +3562,10 @@ }, { "include": "#punctuation-comma" + }, + { + "name": "keyword.operator.assignment.ts", + "match": "(=)(?!>)" } ] }, @@ -3897,13 +3934,10 @@ "include": "#typeof-operator" }, { - "begin": "(?:([&|])|(=(?!>)))(?=\\s*\\{)", + "begin": "([&|\\*])(?=\\s*\\{)", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.ts" - }, - "2": { - "name": "keyword.operator.assignment.ts" } }, "end": "(?<=\\})", @@ -3914,13 +3948,10 @@ ] }, { - "begin": "([&|])|(=(?!>))", + "begin": "[&|\\*]", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.ts" - }, - "2": { - "name": "keyword.operator.assignment.ts" } }, "end": "(?=\\S)" @@ -4052,7 +4083,7 @@ "patterns": [ { "name": "string.template.ts", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", "beginCaptures": { "1": { "name": "entity.name.function.tagged-template.ts" diff --git a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json index bb8426dd854..b58cdd088f1 100644 --- a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json +++ b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/858d33f03943e4ec040e81cbabbc3f7892157c18", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/d33674e802be357bff20cf8b0a4c966be54c39c4", "name": "TypeScriptReact", "scopeName": "source.tsx", "patterns": [ @@ -93,6 +93,10 @@ }, { "include": "#export-declaration" + }, + { + "name": "storage.modifier.tsx", + "match": "(?)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", + "captures": { + "1": { + "name": "meta.definition.property.tsx entity.name.function.tsx" }, - { - "include": "#string" - }, - { - "include": "#array-literal" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#comment" - }, - { - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(\\?)?(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$))) |\n(:\\s*(=>|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ((<\\s*$)|([\\(]\\s*([\\{\\[]\\s*)?$)) |\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)?\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\)))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", - "captures": { - "1": { - "name": "meta.definition.property.tsx entity.name.function.tsx" - }, - "2": { - "name": "keyword.operator.optional.tsx" - } - } - }, - { - "name": "meta.definition.property.tsx variable.object.property.tsx", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.tsx", - "match": "\\?" + "2": { + "name": "keyword.operator.optional.tsx" } - ] + } + }, + { + "name": "meta.definition.property.tsx variable.object.property.tsx", + "match": "[_$[:alpha:]][_$[:alnum:]]*" + }, + { + "name": "keyword.operator.optional.tsx", + "match": "\\?" } ] }, @@ -1107,21 +1113,24 @@ }, "function-declaration": { "name": "meta.function.tsx", - "begin": "(?\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.tsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3495,6 +3528,10 @@ }, { "include": "#punctuation-comma" + }, + { + "name": "keyword.operator.assignment.tsx", + "match": "(=)(?!>)" } ] }, @@ -3863,13 +3900,10 @@ "include": "#typeof-operator" }, { - "begin": "(?:([&|])|(=(?!>)))(?=\\s*\\{)", + "begin": "([&|\\*])(?=\\s*\\{)", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.tsx" - }, - "2": { - "name": "keyword.operator.assignment.tsx" } }, "end": "(?<=\\})", @@ -3880,13 +3914,10 @@ ] }, { - "begin": "([&|])|(=(?!>))", + "begin": "[&|\\*]", "beginCaptures": { - "1": { + "0": { "name": "keyword.operator.type.tsx" - }, - "2": { - "name": "keyword.operator.assignment.tsx" } }, "end": "(?=\\S)" @@ -4018,7 +4049,7 @@ "patterns": [ { "name": "string.template.tsx", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", + "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(\\*(?=\\s*[,>]))|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)`)", "beginCaptures": { "1": { "name": "entity.name.function.tagged-template.tsx" From 2719dec19803a3eca4faea93c0ff228a9136115d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 20 Aug 2018 15:50:37 +0200 Subject: [PATCH 21/44] Update markdown grammar Fixes #55635 --- .../syntaxes/markdown.tmLanguage.json | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index d49d0688467..b1ca0418053 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/4504240cdb13a4640f64fc98a0adb858226a879e", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/826a9c47f16a3d567c3691636fd19f189f65fca5", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -165,6 +165,9 @@ { "include": "#fenced_code_block_dart" }, + { + "include": "#fenced_code_block_handlebars" + }, { "include": "#fenced_code_block_unknown" }, @@ -1685,6 +1688,39 @@ } ] }, + "fenced_code_block_handlebars": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(handlebars|hbs)(\\s+[^`~]*)?$)", + "name": "markup.fenced_code.block.markdown", + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "beginCaptures": { + "3": { + "name": "punctuation.definition.markdown" + }, + "5": { + "name": "fenced_code.block.language" + }, + "6": { + "name": "fenced_code.block.language.attributes" + } + }, + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", + "contentName": "meta.embedded.block.handlebars", + "patterns": [ + { + "include": "text.html.handlebars" + } + ] + } + ] + }, "fenced_code_block_unknown": { "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?=([^`~]*)?$)", "beginCaptures": { @@ -1994,7 +2030,7 @@ "while": "(^|\\G)([ ]{4}|\\t)" }, "separator": { - "match": "(^|\\G)[ ]{0,3}([\\*\\-\\_])([ ]{0,2}\\2){2,}[ \\t]*$\\n?", + "match": "(^|\\G)[ ]{0,3}([*-_])([ ]{0,2}\\2){2,}[ \\t]*$\\n?", "name": "meta.separator.markdown" } } From 95bdfe00647f0b6f8fc7d76cbcf734b664f41df8 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 15:53:15 +0200 Subject: [PATCH 22/44] debug: move firstSessionStart to view model --- .../parts/debug/common/debugViewModel.ts | 30 ++++++++++--------- .../debug/electron-browser/debugService.ts | 8 ++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debugViewModel.ts b/src/vs/workbench/parts/debug/common/debugViewModel.ts index c5816ddb628..efb8ee26930 100644 --- a/src/vs/workbench/parts/debug/common/debugViewModel.ts +++ b/src/vs/workbench/parts/debug/common/debugViewModel.ts @@ -9,6 +9,8 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c export class ViewModel implements IViewModel { + firstSessionStart = true; + private _focusedStackFrame: IStackFrame; private _focusedSession: ISession; private _focusedThread: IThread; @@ -32,15 +34,15 @@ export class ViewModel implements IViewModel { this.loadedScriptsSupportedContextKey = CONTEXT_LOADED_SCRIPTS_SUPPORTED.bindTo(contextKeyService); } - public getId(): string { + getId(): string { return 'root'; } - public get focusedSession(): ISession { + get focusedSession(): ISession { return this._focusedSession; } - public get focusedThread(): IThread { + get focusedThread(): IThread { if (this._focusedStackFrame) { return this._focusedStackFrame.thread; } @@ -54,11 +56,11 @@ export class ViewModel implements IViewModel { return undefined; } - public get focusedStackFrame(): IStackFrame { + get focusedStackFrame(): IStackFrame { return this._focusedStackFrame; } - public setFocus(stackFrame: IStackFrame, thread: IThread, session: ISession, explicit: boolean): void { + setFocus(stackFrame: IStackFrame, thread: IThread, session: ISession, explicit: boolean): void { let shouldEmit = this._focusedSession !== session || this._focusedThread !== thread || this._focusedStackFrame !== stackFrame; if (this._focusedSession !== session) { @@ -75,42 +77,42 @@ export class ViewModel implements IViewModel { } } - public get onDidFocusSession(): Event { + get onDidFocusSession(): Event { return this._onDidFocusSession.event; } - public get onDidFocusStackFrame(): Event<{ stackFrame: IStackFrame, explicit: boolean }> { + get onDidFocusStackFrame(): Event<{ stackFrame: IStackFrame, explicit: boolean }> { return this._onDidFocusStackFrame.event; } - public getSelectedExpression(): IExpression { + getSelectedExpression(): IExpression { return this.selectedExpression; } - public setSelectedExpression(expression: IExpression) { + setSelectedExpression(expression: IExpression) { this.selectedExpression = expression; this.expressionSelectedContextKey.set(!!expression); this._onDidSelectExpression.fire(expression); } - public get onDidSelectExpression(): Event { + get onDidSelectExpression(): Event { return this._onDidSelectExpression.event; } - public getSelectedFunctionBreakpoint(): IFunctionBreakpoint { + getSelectedFunctionBreakpoint(): IFunctionBreakpoint { return this.selectedFunctionBreakpoint; } - public setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void { + setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void { this.selectedFunctionBreakpoint = functionBreakpoint; this.breakpointSelectedContextKey.set(!!functionBreakpoint); } - public isMultiSessionView(): boolean { + isMultiSessionView(): boolean { return this.multiSessionView; } - public setMultiSessionView(isMultiSessionView: boolean): void { + setMultiSessionView(isMultiSessionView: boolean): void { this.multiSessionView = isMultiSessionView; } } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 6499553b46c..75bea9f8577 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -75,7 +75,6 @@ export class DebugService implements IDebugService { private debugState: IContextKey; private inDebugMode: IContextKey; private breakpointsToSendOnResourceSaved: Set; - private firstSessionStart: boolean; private skipRunningTask: boolean; private previousState: State; @@ -117,7 +116,6 @@ export class DebugService implements IDebugService { this.loadExceptionBreakpoints(), this.loadWatchExpressions()); this.toDispose.push(this.model); this.viewModel = new ViewModel(contextKeyService); - this.firstSessionStart = true; this.registerListeners(); } @@ -646,16 +644,16 @@ export class DebugService implements IDebugService { this._onDidNewSession.fire(session); const internalConsoleOptions = resolved.internalConsoleOptions || this.configurationService.getValue('debug').internalConsoleOptions; - if (internalConsoleOptions === 'openOnSessionStart' || (this.firstSessionStart && internalConsoleOptions === 'openOnFirstSessionStart')) { + if (internalConsoleOptions === 'openOnSessionStart' || (this.viewModel.firstSessionStart && internalConsoleOptions === 'openOnFirstSessionStart')) { this.panelService.openPanel(REPL_ID, false).done(undefined, errors.onUnexpectedError); } const openDebug = this.configurationService.getValue('debug').openDebug; // Open debug viewlet based on the visibility of the side bar and openDebug setting - if (openDebug === 'openOnSessionStart' || (openDebug === 'openOnFirstSessionStart' && this.firstSessionStart)) { + if (openDebug === 'openOnSessionStart' || (openDebug === 'openOnFirstSessionStart' && this.viewModel.firstSessionStart)) { this.viewletService.openViewlet(VIEWLET_ID); } - this.firstSessionStart = false; + this.viewModel.firstSessionStart = false; this.debugType.set(resolved.type); if (this.model.getSessions().length > 1) { From b871eb5db1669d5b0d14a230aae531114ca1e837 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 20 Aug 2018 15:53:32 +0200 Subject: [PATCH 23/44] :lipstick: remove outdated comment --- src/vs/workbench/electron-browser/bootstrap/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index 8cbef8ef0a0..74ad36e324a 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// Warning: Do not use the `let` declarator in this file, it breaks our minification - 'use strict'; /*global window,document,define*/ From 1cd754493fe8b90c237a93759fe2ef43c368d088 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 16:02:55 +0200 Subject: [PATCH 24/44] debug: fix initializing state --- .../parts/debug/electron-browser/debugService.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 75bea9f8577..1a54c5824b4 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -76,6 +76,7 @@ export class DebugService implements IDebugService { private inDebugMode: IContextKey; private breakpointsToSendOnResourceSaved: Set; private skipRunningTask: boolean; + private initializing = false; private previousState: State; constructor( @@ -308,6 +309,9 @@ export class DebugService implements IDebugService { if (focusedSession) { return focusedSession.state; } + if (this.initializing) { + return State.Initializing; + } return State.Inactive; } @@ -581,6 +585,8 @@ export class DebugService implements IDebugService { } private createSession(launch: ILaunch, config: IConfig, unresolvedConfig: IConfig, sessionId: string): TPromise { + this.initializing = true; + this.onStateChange(); return this.textFileService.saveAll().then(() => this.substituteVariables(launch, config).then(resolvedConfig => { @@ -621,7 +627,10 @@ export class DebugService implements IDebugService { return launch && launch.openConfigFile(false).then(editor => void 0); }) - ); + ).then(() => { + this.initializing = false; + this.onStateChange(); + }); } private doCreateSession(root: IWorkspaceFolder, configuration: { resolved: IConfig, unresolved: IConfig }, sessionId: string): TPromise { From 8281fa7fadd56655744e747f8d2d138ba34c46b8 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 16:18:45 +0200 Subject: [PATCH 25/44] do not attempt edit operation for for read-only editors fixes #53257 --- src/vs/editor/common/services/resolverService.ts | 2 ++ src/vs/editor/standalone/browser/simpleServices.ts | 4 ++++ .../services/bulkEdit/electron-browser/bulkEditService.ts | 3 +++ src/vs/workbench/services/textfile/common/textfiles.ts | 2 -- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/services/resolverService.ts b/src/vs/editor/common/services/resolverService.ts index 173713e7018..56dca5511ff 100644 --- a/src/vs/editor/common/services/resolverService.ts +++ b/src/vs/editor/common/services/resolverService.ts @@ -42,4 +42,6 @@ export interface ITextEditorModel extends IEditorModel { * Provides access to the underlying `ITextModel`. */ textEditorModel: ITextModel; + + isReadonly(): boolean; } diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 231c2e182c3..e73c429819f 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -69,6 +69,10 @@ export class SimpleModel implements ITextEditorModel { return this.model; } + public isReadonly(): boolean { + return false; + } + public dispose(): void { this._onDispose.fire(); } diff --git a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts index e120c966d99..e7ab928dda6 100644 --- a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts @@ -180,6 +180,9 @@ class BulkEditModel implements IDisposable { if (!model || !model.textEditorModel) { throw new Error(`Cannot load file ${key}`); } + if (model.isReadonly) { + throw new Error(localize('editorIsReadonly', "Cannot edit a read-only editor.")); + } let task: ModelEditTask; if (this._editor && this._editor.getModel().uri.toString() === model.textEditorModel.uri.toString()) { diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index 132e8b15c47..008c6d19155 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -254,8 +254,6 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport isResolved(): boolean; - isReadonly(): boolean; - isDisposed(): boolean; } From 0e3a2219afbeed2996549468f6d656ce4713aeab Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 16:49:37 +0200 Subject: [PATCH 26/44] open editors: focus active group even if it does not have an editor fixes #56806 --- .../parts/files/electron-browser/views/openEditorsView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts index a9eb1724a80..58bc06b153f 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts @@ -389,7 +389,7 @@ export class OpenEditorsView extends ViewletPanel { } private focusActiveEditor(): void { - if (this.editorGroupService.activeGroup && this.editorGroupService.activeGroup.activeEditor /* could be empty */) { + if (this.editorGroupService.activeGroup) { const index = this.getIndex(this.editorGroupService.activeGroup, this.editorGroupService.activeGroup.activeEditor); this.list.setFocus([index]); this.list.setSelection([index]); From c1a965c63c1d3cc13f57b8ec09ef49f89d8d79db Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 20 Aug 2018 16:54:37 +0200 Subject: [PATCH 27/44] debug: npe fixes #56666 --- .../parts/debug/electron-browser/debugConfigurationManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 7a0cba2221a..2d2fd7ce3bc 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -350,7 +350,7 @@ export class ConfigurationManager implements IConfigurationManager { const picks = candidates.map(c => ({ label: c.label, debugger: c })); return this.quickInputService.pick<(typeof picks)[0]>([...picks, { type: 'separator' }, { label: 'More...', debugger: undefined }], { placeHolder: nls.localize('selectDebug', "Select Environment") }) .then(picked => { - if (picked.debugger) { + if (picked && picked.debugger) { return picked.debugger; } if (picked) { From 410c161181eda613d35016f2cd34b8b59c128ca6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 20 Aug 2018 16:50:32 +0200 Subject: [PATCH 28/44] Update markdown grammar Fixes #56735 --- .../markdown-basics/syntaxes/markdown.tmLanguage.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index b1ca0418053..fd2e9302712 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/826a9c47f16a3d567c3691636fd19f189f65fca5", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/082f5ac70a35e7a0979c8450729d216b59789ad6", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -2094,7 +2094,7 @@ "name": "meta.other.valid-ampersand.markdown" }, "bold": { - "begin": "(?x)\n ((?]*+> # HTML tags\n | (?`+)([^`]|(?!(?(?!`))`)*+\\k\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (? # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whitespace\n ? # URL\n [ \\t]*+ # Optional whitespace\n ( # Optional Title\n (?['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=__\\b|\\*\\*)\\1 # Close\n )\n", + "begin": "(?x)\n (\\*\\*(?=\\w)|(?<!\\w)\\*\\*|(?<!\\w)\\b__)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whitespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whitespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=__\\b|\\*\\*)\\1 # Close\n )\n", "captures": { "1": { "name": "punctuation.definition.bold.markdown" @@ -2236,7 +2236,7 @@ "name": "meta.image.reference.markdown" }, "italic": { - "begin": "(?x) (\\*\\b|\\b_)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whtiespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whtiespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | \\1\\1 # Must be bold closer\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=_\\b|\\*)\\1 # Close\n )\n", + "begin": "(?x) (\\*(?=\\w)|(?<!\\w)\\*|(?<!\\w)\\b_)(?=\\S) # Open\n (?=\n (\n <[^>]*+> # HTML tags\n | (?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>\n # Raw\n | \\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+ # Escapes\n | \\[\n (\n (?<square> # Named group\n [^\\[\\]\\\\] # Match most chars\n | \\\\. # Escaped chars\n | \\[ \\g<square>*+ \\] # Nested brackets\n )*+\n \\]\n (\n ( # Reference Link\n [ ]? # Optional space\n \\[[^\\]]*+\\] # Ref name\n )\n | ( # Inline Link\n \\( # Opening paren\n [ \\t]*+ # Optional whtiespace\n <?(.*?)>? # URL\n [ \\t]*+ # Optional whtiespace\n ( # Optional Title\n (?<title>['\"])\n (.*?)\n \\k<title>\n )?\n \\)\n )\n )\n )\n | \\1\\1 # Must be bold closer\n | (?!(?<=\\S)\\1). # Everything besides\n # style closer\n )++\n (?<=\\S)(?=_\\b|\\*)\\1 # Close\n )\n", "captures": { "1": { "name": "punctuation.definition.italic.markdown" From 94c4f0a47d752f00d4848cde3e1cab8c91b53d4e Mon Sep 17 00:00:00 2001 From: Matt Bierner <matb@microsoft.com> Date: Mon, 20 Aug 2018 16:59:43 +0200 Subject: [PATCH 29/44] Update markdown grammar Fixes #3948 --- .../markdown-basics/syntaxes/markdown.tmLanguage.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index fd2e9302712..1036f52cab4 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/082f5ac70a35e7a0979c8450729d216b59789ad6", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/935f7a6d1da73e16231be18c545d7991d3698075", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -189,7 +189,7 @@ "begin": "(^|\\G)[ ]{0,3}(>) ?", "captures": { "2": { - "name": "beginning.punctuation.definition.quote.markdown" + "name": "punctuation.definition.quote.begin.markdown" } }, "name": "markup.quote.markdown", @@ -1973,7 +1973,7 @@ "begin": "(^|\\G)([ ]{0,3})([*+-])([ ]{1,3}|\\t)", "beginCaptures": { "3": { - "name": "beginning.punctuation.definition.list.markdown" + "name": "punctuation.definition.list.begin.markdown" } }, "comment": "Currently does not support un-indented second lines.", @@ -1992,7 +1992,7 @@ "begin": "(^|\\G)([ ]{0,3})([0-9]+\\.)([ ]{1,3}|\\t)", "beginCaptures": { "3": { - "name": "beginning.punctuation.definition.list.markdown" + "name": "punctuation.definition.list.begin.markdown" } }, "name": "markup.list.numbered.markdown", From 9da44453a0cf299a2f7ebc6fb7f3e9276e0439d9 Mon Sep 17 00:00:00 2001 From: Matt Bierner <matb@microsoft.com> Date: Mon, 20 Aug 2018 17:01:55 +0200 Subject: [PATCH 30/44] Update grammar tests --- .../test/colorize-results/test_md.json | 150 +++++++++--------- .../test/colorize-results/test_ts.json | 4 +- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/extensions/markdown-basics/test/colorize-results/test_md.json b/extensions/markdown-basics/test/colorize-results/test_md.json index dc9ce77ffe7..5663fd051bd 100644 --- a/extensions/markdown-basics/test/colorize-results/test_md.json +++ b/extensions/markdown-basics/test/colorize-results/test_md.json @@ -1211,12 +1211,12 @@ }, { "c": "*", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1244,12 +1244,12 @@ }, { "c": "-", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1277,12 +1277,12 @@ }, { "c": "+", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1321,12 +1321,12 @@ }, { "c": "+", - "t": "text.html.markdown markup.list.unnumbered.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1596,12 +1596,12 @@ }, { "c": ">", - "t": "text.html.markdown markup.quote.markdown beginning.punctuation.definition.quote.markdown", + "t": "text.html.markdown markup.quote.markdown punctuation.definition.quote.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_plus": "beginning.punctuation.definition.quote.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_vs": "beginning.punctuation.definition.quote.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1629,23 +1629,23 @@ }, { "c": ">", - "t": "text.html.markdown markup.quote.markdown beginning.punctuation.definition.quote.markdown", + "t": "text.html.markdown markup.quote.markdown punctuation.definition.quote.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_plus": "beginning.punctuation.definition.quote.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_vs": "beginning.punctuation.definition.quote.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, { "c": ">", - "t": "text.html.markdown markup.quote.markdown markup.quote.markdown beginning.punctuation.definition.quote.markdown", + "t": "text.html.markdown markup.quote.markdown markup.quote.markdown punctuation.definition.quote.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_plus": "beginning.punctuation.definition.quote.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_vs": "beginning.punctuation.definition.quote.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1673,12 +1673,12 @@ }, { "c": "1.", - "t": "text.html.markdown markup.list.numbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.numbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1717,12 +1717,12 @@ }, { "c": ">", - "t": "text.html.markdown markup.list.numbered.markdown markup.quote.markdown beginning.punctuation.definition.quote.markdown", + "t": "text.html.markdown markup.list.numbered.markdown markup.quote.markdown punctuation.definition.quote.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_plus": "beginning.punctuation.definition.quote.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.quote.markdown: #6A9955", - "light_vs": "beginning.punctuation.definition.quote.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1750,12 +1750,12 @@ }, { "c": "2.", - "t": "text.html.markdown markup.list.numbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.numbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -1783,12 +1783,12 @@ }, { "c": "3.", - "t": "text.html.markdown markup.list.numbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.numbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -2245,12 +2245,12 @@ }, { "c": "*", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -2278,12 +2278,12 @@ }, { "c": "*", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -2421,12 +2421,12 @@ }, { "c": "*", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, @@ -2454,12 +2454,12 @@ }, { "c": "*", - "t": "text.html.markdown markup.list.unnumbered.markdown beginning.punctuation.definition.list.markdown", + "t": "text.html.markdown markup.list.unnumbered.markdown punctuation.definition.list.begin.markdown", "r": { - "dark_plus": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_plus": "beginning.punctuation.definition.list.markdown: #0451A5", - "dark_vs": "beginning.punctuation.definition.list.markdown: #6796E6", - "light_vs": "beginning.punctuation.definition.list.markdown: #0451A5", + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", "hc_black": "default: #FFFFFF" } }, diff --git a/extensions/typescript-basics/test/colorize-results/test_ts.json b/extensions/typescript-basics/test/colorize-results/test_ts.json index 3246facbff2..bf74c1c2174 100644 --- a/extensions/typescript-basics/test/colorize-results/test_ts.json +++ b/extensions/typescript-basics/test/colorize-results/test_ts.json @@ -1860,7 +1860,7 @@ }, { "c": " ", - "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts", + "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.field.declaration.ts", "r": { "dark_plus": "default: #D4D4D4", "light_plus": "default: #000000", @@ -1871,7 +1871,7 @@ }, { "c": "world", - "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts variable.other.readwrite.ts", + "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.field.declaration.ts meta.definition.property.ts variable.object.property.ts", "r": { "dark_plus": "variable: #9CDCFE", "light_plus": "variable: #001080", From 53e57b5ea03e19ec1002f1c0a2d69fa1dd2cc01b Mon Sep 17 00:00:00 2001 From: isidor <inikolic@microsoft.com> Date: Mon, 20 Aug 2018 17:44:46 +0200 Subject: [PATCH 31/44] longTitle should be absolute fixes #56550 --- src/vs/workbench/parts/files/common/editors/fileEditorInput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts index 6f171a925b3..232a677b82c 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorInput.ts @@ -175,7 +175,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { @memoize private get longTitle(): string { - return this.uriLabelService.getLabel(this.resource, true); + return this.uriLabelService.getLabel(this.resource); } getTitle(verbosity: Verbosity): string { From f7b8c9b7df54f23b02fb36ba0cb12a5a96c8c4e9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken <johannes.rieken@gmail.com> Date: Mon, 20 Aug 2018 17:56:20 +0200 Subject: [PATCH 32/44] perf - tweak data for --prof-append-timers --- .../performance/electron-browser/startupTimingsAppender.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/performance/electron-browser/startupTimingsAppender.ts b/src/vs/workbench/parts/performance/electron-browser/startupTimingsAppender.ts index a59a7ce84e9..9bf3aeb1cf9 100644 --- a/src/vs/workbench/parts/performance/electron-browser/startupTimingsAppender.ts +++ b/src/vs/workbench/parts/performance/electron-browser/startupTimingsAppender.ts @@ -34,7 +34,7 @@ class StartupTimingsAppender implements IWorkbenchContribution { timerService.startupMetrics ]).then(([, startupMetrics]) => { - return nfcall(appendFile, appendTo, `${product.nameShort}\t${product.commit || '0000000'}\t${Date.now()}\t${startupMetrics.ellapsed}\n`); + return nfcall(appendFile, appendTo, `${startupMetrics.ellapsed}\t${product.nameLong}\t${product.commit || '0000000'}\n`); }).then(() => { windowsService.quit(); }).catch(err => { From 2dc09277aa1611e7d7099f2d6eb5b43b37f13183 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero <benjpas@microsoft.com> Date: Mon, 20 Aug 2018 18:46:14 +0200 Subject: [PATCH 33/44] Merge "Terminal" and "Task" menu (fixes #56836) --- src/vs/code/electron-main/menus.ts | 69 +++++++------------ src/vs/platform/actions/common/actions.ts | 1 - .../browser/parts/titlebar/menubarControl.ts | 9 +-- .../electron-browser/task.contribution.ts | 28 ++++---- .../parts/terminal/common/terminalMenu.ts | 66 ++---------------- 5 files changed, 44 insertions(+), 129 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 9d5657cff26..0f11f0d2cb0 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -242,16 +242,16 @@ export class CodeMenu { const gotoMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go")), submenu: gotoMenu }); this.setGotoMenu(gotoMenu); - // Terminal - const terminalMenu = new Menu(); - const terminalMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "Ter&&minal")), submenu: terminalMenu }); - this.setTerminalMenu(terminalMenu); - // Debug const debugMenu = new Menu(); const debugMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug")), submenu: debugMenu }); this.setDebugMenu(debugMenu); + // Terminal + const terminalMenu = new Menu(); + const terminalMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal")), submenu: terminalMenu }); + this.setTerminalMenu(terminalMenu); + // Mac: Window let macWindowMenuItem: Electron.MenuItem; if (isMacintosh) { @@ -265,10 +265,6 @@ export class CodeMenu { const helpMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mHelp', comment: ['&& denotes a mnemonic'] }, "&&Help")), submenu: helpMenu, role: 'help' }); this.setHelpMenu(helpMenu); - // Tasks - const taskMenu = new Menu(); - const taskMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mTask', comment: ['&& denotes a mnemonic'] }, "&&Tasks")), submenu: taskMenu }); - this.setTaskMenu(taskMenu); // Menu Structure if (macApplicationMenuItem) { @@ -280,9 +276,8 @@ export class CodeMenu { menubar.append(selectionMenuItem); menubar.append(viewMenuItem); menubar.append(gotoMenuItem); - menubar.append(terminalMenuItem); menubar.append(debugMenuItem); - menubar.append(taskMenuItem); + menubar.append(terminalMenuItem); if (macWindowMenuItem) { menubar.append(macWindowMenuItem); @@ -885,28 +880,33 @@ export class CodeMenu { private setTerminalMenu(terminalMenu: Electron.Menu): void { const newTerminal = this.createMenuItem(nls.localize({ key: 'miNewTerminal', comment: ['&& denotes a mnemonic'] }, "&&New Terminal"), 'workbench.action.terminal.new'); const splitTerminal = this.createMenuItem(nls.localize({ key: 'miSplitTerminal', comment: ['&& denotes a mnemonic'] }, "&&Split Terminal"), 'workbench.action.terminal.split'); - const killTerminal = this.createMenuItem(nls.localize({ key: 'miKillTerminal', comment: ['&& denotes a mnemonic'] }, "&&Kill Terminal"), 'workbench.action.terminal.kill'); - const clear = this.createMenuItem(nls.localize({ key: 'miClear', comment: ['&& denotes a mnemonic'] }, "&&Clear"), 'workbench.action.terminal.clear'); + const runActiveFile = this.createMenuItem(nls.localize({ key: 'miRunActiveFile', comment: ['&& denotes a mnemonic'] }, "Run &&Active File"), 'workbench.action.terminal.runActiveFile'); const runSelectedText = this.createMenuItem(nls.localize({ key: 'miRunSelectedText', comment: ['&& denotes a mnemonic'] }, "Run &&Selected Text"), 'workbench.action.terminal.runSelectedText'); - const scrollToPreviousCommand = this.createMenuItem(nls.localize({ key: 'miScrollToPreviousCommand', comment: ['&& denotes a mnemonic'] }, "Scroll To Previous Command"), 'workbench.action.terminal.scrollToPreviousCommand'); - const scrollToNextCommand = this.createMenuItem(nls.localize({ key: 'miScrollToNextCommand', comment: ['&& denotes a mnemonic'] }, "Scroll To Next Command"), 'workbench.action.terminal.scrollToNextCommand'); - const selectToPreviousCommand = this.createMenuItem(nls.localize({ key: 'miSelectToPreviousCommand', comment: ['&& denotes a mnemonic'] }, "Select To Previous Command"), 'workbench.action.terminal.selectToPreviousCommand'); - const selectToNextCommand = this.createMenuItem(nls.localize({ key: 'miSelectToNextCommand', comment: ['&& denotes a mnemonic'] }, "Select To Next Command"), 'workbench.action.terminal.selectToNextCommand'); + + const runTask = this.createMenuItem(nls.localize({ key: 'miRunTask', comment: ['&& denotes a mnemonic'] }, "&&Run Task..."), 'workbench.action.tasks.runTask'); + const buildTask = this.createMenuItem(nls.localize({ key: 'miBuildTask', comment: ['&& denotes a mnemonic'] }, "Run &&Build Task..."), 'workbench.action.tasks.build'); + const showTasks = this.createMenuItem(nls.localize({ key: 'miRunningTask', comment: ['&& denotes a mnemonic'] }, "Show Runnin&&g Tasks..."), 'workbench.action.tasks.showTasks'); + const restartTask = this.createMenuItem(nls.localize({ key: 'miRestartTask', comment: ['&& denotes a mnemonic'] }, "R&&estart Running Task..."), 'workbench.action.tasks.restartTask'); + const terminateTask = this.createMenuItem(nls.localize({ key: 'miTerminateTask', comment: ['&& denotes a mnemonic'] }, "&&Terminate Task..."), 'workbench.action.tasks.terminate'); + const configureTask = this.createMenuItem(nls.localize({ key: 'miConfigureTask', comment: ['&& denotes a mnemonic'] }, "&&Configure Tasks..."), 'workbench.action.tasks.configureTaskRunner'); + const configureBuildTask = this.createMenuItem(nls.localize({ key: 'miConfigureBuildTask', comment: ['&& denotes a mnemonic'] }, "Configure De&&fault Build Task..."), 'workbench.action.tasks.configureDefaultBuildTask'); const menuItems: MenuItem[] = [ newTerminal, splitTerminal, - killTerminal, __separator__(), - clear, + runTask, + buildTask, runActiveFile, runSelectedText, __separator__(), - scrollToPreviousCommand, - scrollToNextCommand, - selectToPreviousCommand, - selectToNextCommand + terminateTask, + restartTask, + showTasks, + __separator__(), + configureTask, + configureBuildTask ]; menuItems.forEach(item => terminalMenu.append(item)); @@ -1087,29 +1087,6 @@ export class CodeMenu { } } - private setTaskMenu(taskMenu: Electron.Menu): void { - const runTask = this.createMenuItem(nls.localize({ key: 'miRunTask', comment: ['&& denotes a mnemonic'] }, "&&Run Task..."), 'workbench.action.tasks.runTask'); - const buildTask = this.createMenuItem(nls.localize({ key: 'miBuildTask', comment: ['&& denotes a mnemonic'] }, "Run &&Build Task..."), 'workbench.action.tasks.build'); - const showTasks = this.createMenuItem(nls.localize({ key: 'miRunningTask', comment: ['&& denotes a mnemonic'] }, "Show Runnin&&g Tasks..."), 'workbench.action.tasks.showTasks'); - const restartTask = this.createMenuItem(nls.localize({ key: 'miRestartTask', comment: ['&& denotes a mnemonic'] }, "R&&estart Running Task..."), 'workbench.action.tasks.restartTask'); - const terminateTask = this.createMenuItem(nls.localize({ key: 'miTerminateTask', comment: ['&& denotes a mnemonic'] }, "&&Terminate Task..."), 'workbench.action.tasks.terminate'); - const configureTask = this.createMenuItem(nls.localize({ key: 'miConfigureTask', comment: ['&& denotes a mnemonic'] }, "&&Configure Tasks..."), 'workbench.action.tasks.configureTaskRunner'); - const configureBuildTask = this.createMenuItem(nls.localize({ key: 'miConfigureBuildTask', comment: ['&& denotes a mnemonic'] }, "Configure De&&fault Build Task..."), 'workbench.action.tasks.configureDefaultBuildTask'); - - [ - //__separator__(), - runTask, - buildTask, - __separator__(), - terminateTask, - restartTask, - showTasks, - __separator__(), - configureTask, - configureBuildTask - ].forEach(item => taskMenu.append(item)); - } - private openAccessibilityOptions(): void { const win = new BrowserWindow({ alwaysOnTop: true, diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index f0ba370d22d..e3095b53b9b 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -97,7 +97,6 @@ export class MenuId { static readonly MenubarSwitchGroupMenu = new MenuId(); static readonly MenubarDebugMenu = new MenuId(); static readonly MenubarNewBreakpointMenu = new MenuId(); - static readonly MenubarTasksMenu = new MenuId(); static readonly MenubarPreferencesMenu = new MenuId(); static readonly MenubarHelpMenu = new MenuId(); static readonly MenubarTerminalMenu = new MenuId(); diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index be531b51d72..fc7cf8af33c 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -69,9 +69,8 @@ export class MenubarControl extends Disposable { 'Selection': IMenu; 'View': IMenu; 'Go': IMenu; - 'Terminal': IMenu; 'Debug': IMenu; - 'Tasks': IMenu; + 'Terminal': IMenu; 'Window'?: IMenu; 'Help': IMenu; [index: string]: IMenu; @@ -83,9 +82,8 @@ export class MenubarControl extends Disposable { 'Selection': nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection"), 'View': nls.localize({ key: 'mView', comment: ['&& denotes a mnemonic'] }, "&&View"), 'Go': nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go"), - 'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "Ter&&minal"), 'Debug': nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"), - 'Tasks': nls.localize({ key: 'mTasks', comment: ['&& denotes a mnemonic'] }, "&&Tasks"), + 'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "Ter&&minal"), 'Help': nls.localize({ key: 'mHelp', comment: ['&& denotes a mnemonic'] }, "&&Help") }; @@ -134,9 +132,8 @@ export class MenubarControl extends Disposable { 'Selection': this._register(this.menuService.createMenu(MenuId.MenubarSelectionMenu, this.contextKeyService)), 'View': this._register(this.menuService.createMenu(MenuId.MenubarViewMenu, this.contextKeyService)), 'Go': this._register(this.menuService.createMenu(MenuId.MenubarGoMenu, this.contextKeyService)), - 'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)), 'Debug': this._register(this.menuService.createMenu(MenuId.MenubarDebugMenu, this.contextKeyService)), - 'Tasks': this._register(this.menuService.createMenu(MenuId.MenubarTasksMenu, this.contextKeyService)), + 'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)), 'Help': this._register(this.menuService.createMenu(MenuId.MenubarHelpMenu, this.contextKeyService)) }; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index f6c79e586a7..0e0288da207 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -2419,8 +2419,8 @@ class TaskService implements ITaskService { } } -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '1_run', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '2_run', command: { id: 'workbench.action.tasks.runTask', title: nls.localize({ key: 'miRunTask', comment: ['&& denotes a mnemonic'] }, "&&Run Task...") @@ -2428,8 +2428,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { order: 1 }); -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '1_run', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '2_run', command: { id: 'workbench.action.tasks.build', title: nls.localize({ key: 'miBuildTask', comment: ['&& denotes a mnemonic'] }, "Run &&Build Task...") @@ -2438,8 +2438,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { }); // Manage Tasks -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '2_manage', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '3_manage', command: { precondition: TASK_RUNNING_STATE, id: 'workbench.action.tasks.showTasks', @@ -2448,8 +2448,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { order: 1 }); -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '2_manage', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '3_manage', command: { precondition: TASK_RUNNING_STATE, id: 'workbench.action.tasks.restartTask', @@ -2458,8 +2458,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { order: 2 }); -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '2_manage', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '3_manage', command: { precondition: TASK_RUNNING_STATE, id: 'workbench.action.tasks.terminate', @@ -2469,8 +2469,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { }); // Configure Tasks -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '3_configure', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '4_configure', command: { id: 'workbench.action.tasks.configureTaskRunner', title: nls.localize({ key: 'miConfigureTask', comment: ['&& denotes a mnemonic'] }, "&&Configure Tasks...") @@ -2478,8 +2478,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { order: 1 }); -MenuRegistry.appendMenuItem(MenuId.MenubarTasksMenu, { - group: '3_configure', +MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { + group: '4_configure', command: { id: 'workbench.action.tasks.configureDefaultBuildTask', title: nls.localize({ key: 'miConfigureBuildTask', comment: ['&& denotes a mnemonic'] }, "Configure De&&fault Build Task...") diff --git a/src/vs/workbench/parts/terminal/common/terminalMenu.ts b/src/vs/workbench/parts/terminal/common/terminalMenu.ts index 0223a9df008..873c8c688a5 100644 --- a/src/vs/workbench/parts/terminal/common/terminalMenu.ts +++ b/src/vs/workbench/parts/terminal/common/terminalMenu.ts @@ -22,9 +22,9 @@ export function setupTerminalMenu() { }); // Manage - const manageGroup = '1_manage'; + const createGroup = '1_create'; MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: manageGroup, + group: createGroup, command: { id: TERMINAL_COMMAND_ID.NEW, title: nls.localize({ key: 'miNewTerminal', comment: ['&& denotes a mnemonic'] }, "&&New Terminal") @@ -32,7 +32,7 @@ export function setupTerminalMenu() { order: 1 }); MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: manageGroup, + group: createGroup, command: { id: TERMINAL_COMMAND_ID.SPLIT, title: nls.localize({ key: 'miSplitTerminal', comment: ['&& denotes a mnemonic'] }, "&&Split Terminal"), @@ -41,34 +41,15 @@ export function setupTerminalMenu() { order: 2 }); - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: manageGroup, - command: { - id: TERMINAL_COMMAND_ID.KILL, - title: nls.localize({ key: 'miKillTerminal', comment: ['&& denotes a mnemonic'] }, "&&Kill Terminal"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, - order: 3 - }); - // Run const runGroup = '2_run'; - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: runGroup, - command: { - id: TERMINAL_COMMAND_ID.CLEAR, - title: nls.localize({ key: 'miClear', comment: ['&& denotes a mnemonic'] }, "&&Clear"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, - order: 1 - }); MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { group: runGroup, command: { id: TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE, title: nls.localize({ key: 'miRunActiveFile', comment: ['&& denotes a mnemonic'] }, "Run &&Active File") }, - order: 2 + order: 3 }); MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { group: runGroup, @@ -76,45 +57,6 @@ export function setupTerminalMenu() { id: TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT, title: nls.localize({ key: 'miRunSelectedText', comment: ['&& denotes a mnemonic'] }, "Run &&Selected Text") }, - order: 3 - }); - - // Navigation - const navigationGroup = '3_navigation'; - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: navigationGroup, - command: { - id: TERMINAL_COMMAND_ID.SCROLL_TO_PREVIOUS_COMMAND, - title: nls.localize({ key: 'miScrollToPreviousCommand', comment: ['&& denotes a mnemonic'] }, "Scroll To Previous Command"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, - order: 1 - }); - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: navigationGroup, - command: { - id: TERMINAL_COMMAND_ID.SCROLL_TO_NEXT_COMMAND, - title: nls.localize({ key: 'miScrollToNextCommand', comment: ['&& denotes a mnemonic'] }, "Scroll To Next Command"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, - order: 2 - }); - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: navigationGroup, - command: { - id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_COMMAND, - title: nls.localize({ key: 'miSelectToPreviousCommand', comment: ['&& denotes a mnemonic'] }, "Select To Previous Command"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, - order: 3 - }); - MenuRegistry.appendMenuItem(MenuId.MenubarTerminalMenu, { - group: navigationGroup, - command: { - id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND, - title: nls.localize({ key: 'miSelectToNextCommand', comment: ['&& denotes a mnemonic'] }, "Select To Next Command"), - precondition: ContextKeyExpr.has('terminalIsOpen') - }, order: 4 }); } From ff8009d5d35b1b9b92317b8989139856761efbaa Mon Sep 17 00:00:00 2001 From: Benjamin Pasero <benjpas@microsoft.com> Date: Mon, 20 Aug 2018 18:46:53 +0200 Subject: [PATCH 34/44] Revert "open editors: focus active group even if it does not have an editor" This reverts commit 0e3a2219afbeed2996549468f6d656ce4713aeab. --- .../parts/files/electron-browser/views/openEditorsView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts index 58bc06b153f..a9eb1724a80 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts @@ -389,7 +389,7 @@ export class OpenEditorsView extends ViewletPanel { } private focusActiveEditor(): void { - if (this.editorGroupService.activeGroup) { + if (this.editorGroupService.activeGroup && this.editorGroupService.activeGroup.activeEditor /* could be empty */) { const index = this.getIndex(this.editorGroupService.activeGroup, this.editorGroupService.activeGroup.activeEditor); this.list.setFocus([index]); this.list.setSelection([index]); From aaa778b5e24c1af3aac43e840dce39ed861423f0 Mon Sep 17 00:00:00 2001 From: Nikolai Vavilov <vvnicholas@gmail.com> Date: Mon, 20 Aug 2018 19:55:12 +0300 Subject: [PATCH 35/44] Use 'r+' with truncation when saving existing files on Windows (#42899) * Use 'r+' with truncation when saving existing files on Windows Opening a file with 'w' flag removes its alternate data streams. To prevent this, extend the logic used for hidden files to all existing files. Fixes: https://github.com/Microsoft/vscode/issues/6363 * adopt truncate for saving as admin --- src/vs/code/node/cli.ts | 21 +++++++++---------- .../files/electron-browser/fileService.ts | 21 ++++++++++--------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 3ca3fd9ec94..a5f35fb14c1 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -87,18 +87,17 @@ export async function main(argv: string[]): Promise<any> { // Write source to target const data = fs.readFileSync(source); - try { + if (isWindows) { + // On Windows we use a different strategy of saving the file + // by first truncating the file and then writing with r+ mode. + // This helps to save hidden files on Windows + // (see https://github.com/Microsoft/vscode/issues/931) and + // prevent removing alternate data streams + // (see https://github.com/Microsoft/vscode/issues/6363) + fs.truncateSync(target, 0); + writeFileAndFlushSync(target, data, { flag: 'r+' }); + } else { writeFileAndFlushSync(target, data); - } catch (error) { - // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file - // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows - // (see https://github.com/Microsoft/vscode/issues/931) - if (isWindows && error.code === 'EPERM') { - fs.truncateSync(target, 0); - writeFileAndFlushSync(target, data, { flag: 'r+' }); - } else { - throw error; - } } // Restore previous mode as needed diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index b91d4371d27..44a594f32b3 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -607,22 +607,23 @@ export class FileService extends Disposable implements IFileService { return addBomPromise.then(addBom => { // 4.) set contents and resolve - return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite).then(void 0, error => { - if (!exists || error.code !== 'EPERM' || !isWindows) { - return TPromise.wrapError(error); - } + if (!exists || !isWindows) { + return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite); + } - // On Windows and if the file exists with an EPERM error, we try a different strategy of saving the file - // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows - // (see https://github.com/Microsoft/vscode/issues/931) + // On Windows and if the file exists, we use a different strategy of saving the file + // by first truncating the file and then writing with r+ mode. This helps to save hidden files on Windows + // (see https://github.com/Microsoft/vscode/issues/931) and prevent removing alternate data streams + // (see https://github.com/Microsoft/vscode/issues/6363) + else { - // 5.) truncate + // 4.) truncate return pfs.truncate(absolutePath, 0).then(() => { - // 6.) set contents (this time with r+ mode) and resolve again + // 5.) set contents (with r+ mode) and resolve return this.doSetContentsAndResolve(resource, absolutePath, value, addBom, encodingToWrite, { flag: 'r+' }); }); - }); + } }); }); }).then(null, error => { From f54c36f7b997a8e5e934397719b28ff0ec1ff45a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero <benjpas@microsoft.com> Date: Mon, 20 Aug 2018 19:03:25 +0200 Subject: [PATCH 36/44] fix tests --- .../services/bulkEdit/electron-browser/bulkEditService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts index e7ab928dda6..8e787b56880 100644 --- a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts @@ -180,7 +180,7 @@ class BulkEditModel implements IDisposable { if (!model || !model.textEditorModel) { throw new Error(`Cannot load file ${key}`); } - if (model.isReadonly) { + if (model.isReadonly()) { throw new Error(localize('editorIsReadonly', "Cannot edit a read-only editor.")); } From 334c4051e0c80c5febb3bc88f9fbb86f75925740 Mon Sep 17 00:00:00 2001 From: Rob Lourens <roblourens@gmail.com> Date: Mon, 20 Aug 2018 11:20:22 -0700 Subject: [PATCH 37/44] Fix #56726 - don't block "shift+f10" in input boxes in the settings tree --- src/vs/base/parts/tree/browser/treeView.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 6b1e97a1a7f..5616313787e 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -1315,15 +1315,15 @@ export class TreeView extends HeightMap { this.didJustPressContextMenuKey = event.keyCode === KeyCode.ContextMenu || (event.shiftKey && event.keyCode === KeyCode.F10); + if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') { + return; // Ignore event if target is a form input field (avoids browser specific issues) + } + if (this.didJustPressContextMenuKey) { event.preventDefault(); event.stopPropagation(); } - if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') { - return; // Ignore event if target is a form input field (avoids browser specific issues) - } - this.context.controller.onKeyDown(this.context.tree, event); } From af9d9ac56087a7b2ec7024cd44c824654a34bc96 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane <ramacfar@microsoft.com> Date: Mon, 20 Aug 2018 12:54:03 -0700 Subject: [PATCH 38/44] Preserve focus on comments panel when selecting comments, fixes https://github.com/Microsoft/vscode-pull-request-github/issues/198 --- .../parts/comments/electron-browser/commentThreadWidget.ts | 3 --- .../workbench/parts/comments/electron-browser/commentsPanel.ts | 1 - 2 files changed, 4 deletions(-) diff --git a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts index 7b3b6262081..992b6092d61 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts @@ -175,8 +175,6 @@ export class ReviewZoneWidget extends ZoneWidget { this.show({ lineNumber: this._commentThread.range.startLineNumber, column: 1 }, 2); } - this._bodyElement.focus(); - if (commentId) { let height = this.editor.getLayoutInfo().height; let matchedNode = this._commentElements.filter(commentNode => commentNode.comment.commentId === commentId); @@ -185,7 +183,6 @@ export class ReviewZoneWidget extends ZoneWidget { const commentCoords = dom.getDomNodePagePosition(matchedNode[0].domNode); this.editor.setScrollTop(this.editor.getTopForLineNumber(this._commentThread.range.startLineNumber) - height / 2 + commentCoords.top - commentThreadCoords.top); - matchedNode[0].focus(); return; } } diff --git a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts index 4701e552987..44c69e089f7 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts @@ -232,7 +232,6 @@ export class CommentsPanel extends Panel { const control = editor.getControl(); if (threadToReveal && isCodeEditor(control)) { const controller = ReviewController.get(control); - console.log(commentToReveal.command); controller.revealCommentThread(threadToReveal, commentToReveal.commentId); } setCommentsForFile = null; From 0b772cda9c53f5ee858fdd6b1f0a0f12b5bddc51 Mon Sep 17 00:00:00 2001 From: Daniel Imms <daimms@microsoft.com> Date: Mon, 20 Aug 2018 15:15:21 -0700 Subject: [PATCH 39/44] Prevent undefined from showing up in terminal dropdown Prefer empty string --- src/vs/workbench/parts/terminal/common/terminalService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index c1650928b9d..69b56fe9739 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -117,7 +117,7 @@ export abstract class TerminalService implements ITerminalService { } public getTabLabels(): string[] { - return this._terminalTabs.filter(tab => tab.terminalInstances.length > 0).map((tab, index) => `${index + 1}: ${tab.title}`); + return this._terminalTabs.filter(tab => tab.terminalInstances.length > 0).map((tab, index) => `${index + 1}: ${tab.title ? tab.title : ''}`); } private _removeTab(tab: ITerminalTab): void { From 61cb8d0ef0cbf10ef72011351458fe2a5b980b13 Mon Sep 17 00:00:00 2001 From: Daniel Imms <daimms@microsoft.com> Date: Mon, 20 Aug 2018 15:47:22 -0700 Subject: [PATCH 40/44] Give terminal process listeners a chance to init --- src/vs/workbench/parts/terminal/node/terminalProcess.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalProcess.ts b/src/vs/workbench/parts/terminal/node/terminalProcess.ts index 5500c17791a..5da6bdacde8 100644 --- a/src/vs/workbench/parts/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/parts/terminal/node/terminalProcess.ts @@ -79,7 +79,11 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { } private _setupTitlePolling() { - this._sendProcessTitle(); + // Send initial timeout async to give event listeners a chance to init + setTimeout(() => { + this._sendProcessTitle(); + }, 0); + // Setup polling setInterval(() => { if (this._currentTitle !== this._ptyProcess.process) { this._sendProcessTitle(); From 32cb4411058c0301f22009a25c7fbbb6581a31b9 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane <ramacfar@microsoft.com> Date: Mon, 20 Aug 2018 15:56:19 -0700 Subject: [PATCH 41/44] Localize strings in commentThreadWidget --- .../electron-browser/commentThreadWidget.ts | 46 +++++++++---------- .../electron-browser/media/review.css | 4 -- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts index 992b6092d61..d5a2d3db43b 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts @@ -99,9 +99,7 @@ export class CommentNode { let INMEM_MODEL_ID = 0; export class ReviewZoneWidget extends ZoneWidget { private _headElement: HTMLElement; - protected _primaryHeading: HTMLElement; - protected _secondaryHeading: HTMLElement; - protected _metaHeading: HTMLElement; + protected _headingLabel: HTMLElement; protected _actionbarWidget: ActionBar; private _bodyElement: HTMLElement; private _commentEditor: ICodeEditor; @@ -205,13 +203,8 @@ export class ReviewZoneWidget extends ZoneWidget { appendTo(this._headElement). getHTMLElement(); - this._primaryHeading = $('span.filename').appendTo(titleElement).getHTMLElement(); - this._secondaryHeading = $('span.dirname').appendTo(titleElement).getHTMLElement(); - this._metaHeading = $('span.meta').appendTo(titleElement).getHTMLElement(); - - if (this._commentThread.comments.length) { - this.createParticipantsLabel(); - } + this._headingLabel = $('span.filename').appendTo(titleElement).getHTMLElement(); + this.createThreadLabel(); const actionsContainer = $('.review-actions').appendTo(this._headElement); this._actionbarWidget = new ActionBar(actionsContainer.getHTMLElement(), {}); @@ -288,8 +281,7 @@ export class ReviewZoneWidget extends ZoneWidget { this._commentThread = commentThread; this._commentElements = newCommentNodeList; - let secondaryHeading = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', '); - $(this._secondaryHeading).safeInnerHtml(secondaryHeading); + this.createThreadLabel(); } protected _doLayout(heightInPixel: number, widthInPixel: number): void { @@ -423,7 +415,6 @@ export class ReviewZoneWidget extends ZoneWidget { if (newCommentThread) { this.createReplyButton(); - this.createParticipantsLabel(); } } @@ -446,20 +437,23 @@ export class ReviewZoneWidget extends ZoneWidget { } } - createParticipantsLabel() { - const primaryHeading = 'Participants:'; - $(this._primaryHeading).safeInnerHtml(primaryHeading); - this._primaryHeading.setAttribute('aria-label', primaryHeading); + private createThreadLabel() { + let label: string; + if (this._commentThread.comments.length) { + const participantsList = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', '); + label = nls.localize('commentThreadParticipants', "Participants: {0}", participantsList); + } else { + label = nls.localize('startThread', "Start discussion"); + } - const secondaryHeading = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', '); - $(this._secondaryHeading).safeInnerHtml(secondaryHeading); - this._secondaryHeading.setAttribute('aria-label', secondaryHeading); + $(this._headingLabel).safeInnerHtml(label); + this._headingLabel.setAttribute('aria-label', label); } - createReplyButton() { + private createReplyButton() { this._reviewThreadReplyButton = <HTMLButtonElement>$('button.review-thread-reply-button').appendTo(this._commentForm).getHTMLElement(); - this._reviewThreadReplyButton.title = 'Reply...'; - this._reviewThreadReplyButton.textContent = 'Reply...'; + this._reviewThreadReplyButton.title = nls.localize('reply', "Reply..."); + this._reviewThreadReplyButton.textContent = nls.localize('reply', "Reply..."); // bind click/escape actions for reviewThreadReplyButton and textArea this._reviewThreadReplyButton.onclick = () => { if (!dom.hasClass(this._commentForm, 'expand')) { @@ -493,7 +487,11 @@ export class ReviewZoneWidget extends ZoneWidget { if (model) { let valueLength = model.getValueLength(); const hasExistingComments = this._commentThread.comments.length > 0; - let placeholder = valueLength > 0 ? '' : (hasExistingComments ? 'Reply... (press Ctrl+Enter to submit)' : 'Type a new comment (press Ctrl+Enter to submit)'); + let placeholder = valueLength > 0 + ? '' + : (hasExistingComments + ? nls.localize('replytoCommentThread', "Reply... (press Ctrl+Enter to submit)") + : nls.localize('createCommentThread', "Type a new comment (press Ctrl+Enter to submit)")); const decorations = [{ range: { startLineNumber: 0, diff --git a/src/vs/workbench/parts/comments/electron-browser/media/review.css b/src/vs/workbench/parts/comments/electron-browser/media/review.css index 6a3d41dd41d..fec55286837 100644 --- a/src/vs/workbench/parts/comments/electron-browser/media/review.css +++ b/src/vs/workbench/parts/comments/electron-browser/media/review.css @@ -223,10 +223,6 @@ cursor: pointer; } -.monaco-editor .review-widget .head .review-title .filename:empty::after { - content: "Start discussion"; -} - .monaco-editor .review-widget .head .review-title .dirname:not(:empty) { font-size: 0.9em; margin-left: 0.5em; From f8168e6c2ed6da949c1b7137e69e0499913b5792 Mon Sep 17 00:00:00 2001 From: Daniel Imms <daimms@microsoft.com> Date: Mon, 20 Aug 2018 16:16:52 -0700 Subject: [PATCH 42/44] Don't request terminal processes before ext host is ready --- .../terminal/node/terminalProcessExtHostProxy.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts b/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts index 52bc33c6fa5..cac16c5ff22 100644 --- a/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/parts/terminal/node/terminalProcessExtHostProxy.ts @@ -7,6 +7,7 @@ import { ITerminalChildProcess } from 'vs/workbench/parts/terminal/node/terminal import { Event, Emitter } from 'vs/base/common/event'; import { ITerminalService, ITerminalProcessExtHostProxy, IShellLaunchConfig } from 'vs/workbench/parts/terminal/common/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; export class TerminalProcessExtHostProxy implements ITerminalChildProcess, ITerminalProcessExtHostProxy { private _disposables: IDisposable[] = []; @@ -32,10 +33,15 @@ export class TerminalProcessExtHostProxy implements ITerminalChildProcess, ITerm shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number, - @ITerminalService private _terminalService: ITerminalService + @ITerminalService private _terminalService: ITerminalService, + @IExtensionService private readonly _extensionService: IExtensionService ) { - // TODO: Return TPromise<boolean> indicating success? Teardown if failure? - this._terminalService.requestExtHostProcess(this, shellLaunchConfig, cols, rows); + this._extensionService.whenInstalledExtensionsRegistered().then(() => { + // TODO: MainThreadTerminalService is not ready at this point, fix this + setTimeout(() => { + this._terminalService.requestExtHostProcess(this, shellLaunchConfig, cols, rows); + }, 0); + }); } public dispose(): void { From 4c05804c47730e88f1e079fd5163516639648cce Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao <ramyar@microsoft.com> Date: Mon, 20 Aug 2018 17:58:50 -0700 Subject: [PATCH 43/44] Update GDPR annotation errors --- .../workbench/services/textfile/common/textFileEditorModel.ts | 4 ++-- .../workbench/services/timer/electron-browser/timerService.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index bc21ebdd62e..b9e1a1a9937 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -357,7 +357,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil if (settingsType) { /* __GDPR__ "settingsRead" : { - "settingsType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "settingsType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('settingsRead', { settingsType }); // Do not log read to user settings.json and .vscode folder as a fileGet event as it ruins our JSON usage data @@ -719,7 +719,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil if (settingsType) { /* __GDPR__ "settingsWritten" : { - "settingsType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "settingsType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('settingsWritten', { settingsType }); // Do not log write to user settings.json and .vscode folder as a filePUT event as it ruins our JSON usage data diff --git a/src/vs/workbench/services/timer/electron-browser/timerService.ts b/src/vs/workbench/services/timer/electron-browser/timerService.ts index feb7c0b467b..3134aa7889c 100644 --- a/src/vs/workbench/services/timer/electron-browser/timerService.ts +++ b/src/vs/workbench/services/timer/electron-browser/timerService.ts @@ -47,7 +47,7 @@ export interface IMemoryInfo { "windowCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "viewletId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "panelId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, - "editorIds": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + "editorIds": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, "timers.ellapsedAppReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedWindowLoad" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, "timers.ellapsedWindowLoadToRequire" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, From 3067e4c30efef358288b6218c409f75dfa74977d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero <benjpas@microsoft.com> Date: Tue, 21 Aug 2018 07:20:52 +0200 Subject: [PATCH 44/44] fix tests more --- .../test/electron-browser/api/mainThreadEditors.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts index 55d3113842c..19ef6688f08 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts @@ -79,6 +79,7 @@ suite('MainThreadEditors', () => { const textEditorModel: ITextEditorModel = new class extends mock<ITextEditorModel>() { textEditorModel = modelService.getModel(resource); }; + textEditorModel.isReadonly = () => false; return TPromise.as(new ImmortalReference(textEditorModel)); } };