diff --git a/.github/feature-requests.yml b/.github/feature-requests.yml deleted file mode 100644 index 18055b8448..0000000000 --- a/.github/feature-requests.yml +++ /dev/null @@ -1,34 +0,0 @@ -{ - typeLabel: { - name: 'feature-request' - }, - candidateMilestone: { - number: 107, - name: 'Backlog Candidates' - }, - approvedMilestone: { - number: 8, - name: 'Backlog' - }, - onLabeled: { - delay: 60, - perform: true - }, - onCandidateMilestoned: { - candidatesComment: "This feature request is now a candidate for our backlog. The community has 60 days to upvote the issue. If it receives 20 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!", - perform: true - }, - onMonitorUpvotes: { - upvoteThreshold: 20, - acceptanceComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!", - perform: true - }, - onMonitorDaysOnCandidateMilestone: { - daysOnMilestone: 60, - warningPeriod: 10, - numberOfCommentsToPreventAutomaticRejection: 20, - rejectionComment: ":slightly_frowning_face: In the last 60 days, this feature request has received less than 20 community upvotes and we closed it. Still a big Thank You to you for taking the time to create this issue! To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!", - warningComment: "This feature request has not yet received the 20 community upvotes it takes to make to our backlog. 10 days to go. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding", - perform: true - } -} diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml new file mode 100644 index 0000000000..ff573a9e10 --- /dev/null +++ b/.github/workflows/feature-request.yml @@ -0,0 +1,36 @@ +name: Feature Request Manager +on: + repository_dispatch: + issues: + types: [labeled, milestoned] + schedule: + - cron: 20 2 * * * # 4:20am Zurich + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: Checkout Actions + if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') + uses: actions/checkout@v2 + with: + repository: 'JacksonKearl/vscode-triage-github-actions' + ref: v20 + - name: Run Feature Request Manager + if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') + uses: ./feature-request + with: + token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}} + candidateMilestoneID: 107 + candidateMilestoneName: Backlog Candidates + backlogMilestoneID: 8 + featureRequestLabel: feature-request + upvotesRequired: 20 + numCommentsOverride: 20 + initComment: "This feature request is now a candidate for our backlog. The community has 60 days to upvote the issue. If it receives 20 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!" + warnComment: "This feature request has not yet received the 20 community upvotes it takes to make to our backlog. 10 days to go. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding" + acceptComment: ":slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!" + rejectComment: ":slightly_frowning_face: In the last 60 days, this feature request has received less than 20 community upvotes and we closed it. Still a big Thank You to you for taking the time to create this issue! To learn more about how we handle feature requests, please see our [documentation](https://aka.ms/vscode-issue-lifecycle).\n\nHappy Coding!" + warnDays: 10 + closeDays: 60 + milestoneDelaySeconds: 60 diff --git a/.vscode/searches/es6.code-search b/.vscode/searches/es6.code-search index 09a841dc69..df7088e5a1 100644 --- a/.vscode/searches/es6.code-search +++ b/.vscode/searches/es6.code-search @@ -2,7 +2,7 @@ # Flags: CaseSensitive WordMatch # ContextLines: 2 -11 results - 3 files +9 results - 4 files src/vs/base/common/arrays.ts: 401 @@ -17,20 +17,14 @@ src/vs/base/common/arrays.ts: 420 */ 421 export function first(array: ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T): T; - 474 - 475 /** - 476: * @deprecated ES6: use `Array.fill` - 477 */ - 478 export function fill(num: number, value: T, arr: T[] = []): T[] { - - 571 - 572 /** - 573: * @deprecated ES6: use `Array.find` - 574 */ - 575 export function find(arr: ArrayLike, predicate: (value: T, index: number, arr: ArrayLike) => any): T | undefined { + 560 + 561 /** + 562: * @deprecated ES6: use `Array.find` + 563 */ + 564 export function find(arr: ArrayLike, predicate: (value: T, index: number, arr: ArrayLike) => any): T | undefined { src/vs/base/common/map.ts: - 9 + 9 10 /** 11: * @deprecated ES6: use `[...SetOrMap.values()]` 12 */ @@ -42,33 +36,28 @@ src/vs/base/common/map.ts: 23 */ 24 export function keys(map: Map): K[] { - 58 - 59 /** - 60: * @deprecated ES6: use `...Map.entries()` - 61 */ - 62 export function mapToSerializable(map: Map): [string, string][] { - - 71 - 72 /** - 73: * @deprecated ES6: use `new Map([[key1, value1],[key2, value2]])` - 74 */ - 75 export function serializableToMap(serializable: [string, string][]): Map { +src/vs/base/common/objects.ts: + 115 + 116 /** + 117: * @deprecated ES6 + 118 */ + 119 export function assign(destination: T): T; src/vs/base/common/strings.ts: - 16 - 17 /** - 18: * @deprecated ES6: use `String.padStart` - 19 */ - 20 export function pad(n: number, l: number, char: string = '0'): string { + 15 + 16 /** + 17: * @deprecated ES6: use `String.padStart` + 18 */ + 19 export function pad(n: number, l: number, char: string = '0'): string { - 147 - 148 /** - 149: * @deprecated ES6: use `String.startsWith` - 150 */ - 151 export function startsWith(haystack: string, needle: string): boolean { + 146 + 147 /** + 148: * @deprecated ES6: use `String.startsWith` + 149 */ + 150 export function startsWith(haystack: string, needle: string): boolean { - 168 - 169 /** - 170: * @deprecated ES6: use `String.endsWith` - 171 */ - 172 export function endsWith(haystack: string, needle: string): boolean { + 167 + 168 /** + 169: * @deprecated ES6: use `String.endsWith` + 170 */ + 171 export function endsWith(haystack: string, needle: string): boolean { diff --git a/build/lib/watch/yarn.lock b/build/lib/watch/yarn.lock index 3f330da176..edbfe1f312 100644 --- a/build/lib/watch/yarn.lock +++ b/build/lib/watch/yarn.lock @@ -230,9 +230,9 @@ for-own@^0.1.4: for-in "^1.0.1" fsevents@~2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.1.tgz#74c64e21df71721845d0c44fe54b7f56b82995a9" - integrity sha512-4FRPXWETxtigtJW/gxzEDsX1LVbPAM93VleB83kZB+ellqbHMkyt2aJfuzNLRvFPnGi6bcE5SvfxgbXPeKteJw== + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== glob-base@^0.3.0: version "0.3.0" @@ -258,9 +258,9 @@ glob-parent@^3.0.1: path-dirname "^1.0.0" glob-parent@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" @@ -405,9 +405,9 @@ kind-of@^3.0.2: is-buffer "^1.1.5" kind-of@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== math-random@^1.0.1: version "1.0.4" @@ -479,9 +479,9 @@ path-is-absolute@^1.0.1: integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= picomatch@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.0.tgz#0fd042f568d08b1ad9ff2d3ec0f0bfb3cb80e177" - integrity sha512-uhnEDzAbrcJ8R3g2fANnSuXZMBtkpSjxTTgn2LeSiQlfmq72enQJWdQllXW24MBLYnA1SBD2vfvx2o0Zw3Ielw== + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^2.3.0: version "2.3.0" @@ -530,9 +530,9 @@ randomatic@^3.0.0: math-random "^1.0.1" readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" diff --git a/extensions/git/package.json b/extensions/git/package.json index 75306b8a78..572fb1692a 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1235,11 +1235,6 @@ } ], "timeline/item/context": [ - { - "command": "git.timeline.openDiff", - "group": "inline", - "when": "config.git.enabled && !git.missing && timelineItem =~ /git:file\\b/" - }, { "command": "git.timeline.openDiff", "group": "1_timeline", diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index 53989138a5..59d9186bf3 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -74,7 +74,7 @@ export class GitTimelineProvider implements TimelineProvider { constructor(private readonly _model: Model) { this.disposable = Disposable.from( _model.onDidOpenRepository(this.onRepositoriesChanged, this), - workspace.registerTimelineProvider(['file', 'git', 'gitlens-git'], this), + workspace.registerTimelineProvider(['file', 'git', 'vscode-remote', 'gitlens-git'], this), ); } diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index 002e4b6d98..7a403536a8 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import * as uuid from 'uuid'; import { keychain } from './common/keychain'; import { GitHubServer } from './githubServer'; import Logger from './common/logger'; @@ -122,7 +123,7 @@ export class GitHubAuthenticationProvider { private async tokenToSession(token: string, scopes: string[]): Promise { const userInfo = await this._githubServer.getUserInfo(token); return { - id: userInfo.id, + id: uuid(), getAccessToken: () => Promise.resolve(token), accountName: userInfo.accountName, scopes: scopes diff --git a/extensions/image-preview/src/extension.ts b/extensions/image-preview/src/extension.ts index 8093a99964..83ec387ce1 100644 --- a/extensions/image-preview/src/extension.ts +++ b/extensions/image-preview/src/extension.ts @@ -23,7 +23,7 @@ export function activate(context: vscode.ExtensionContext) { const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry); - context.subscriptions.push(vscode.window.registerCustomEditorProvider(PreviewManager.viewType, previewManager)); + context.subscriptions.push(vscode.window.registerCustomEditorProvider2(PreviewManager.viewType, previewManager)); context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => { previewManager.activePreview?.zoomIn(); diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index ae5b4a9e07..b66807fddf 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -14,7 +14,7 @@ "dependencies": { "jsonc-parser": "^2.2.1", "request-light": "^0.2.5", - "vscode-json-languageservice": "^3.5.1", + "vscode-json-languageservice": "^3.5.2", "vscode-languageserver": "^6.1.1", "vscode-uri": "^2.1.1" }, diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index f6b78986f8..eb34e96baa 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -80,10 +80,10 @@ request-light@^0.2.5: https-proxy-agent "^2.2.3" vscode-nls "^4.1.1" -vscode-json-languageservice@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.5.1.tgz#75779d466107cbc8c4cc9828df100df71c1870f8" - integrity sha512-F8jPqcAC1mbQOMKvGYS4dGEw9JCZxVEi7tc5ASZLfcfwKq2URZKB4fOtdy1GEsTLsrW11tVrBjEPntpXzqp/NA== +vscode-json-languageservice@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz#4b898140a8e581359c10660845a4cae15dcbb4f9" + integrity sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A== dependencies: jsonc-parser "^2.2.1" vscode-languageserver-textdocument "^1.0.1" diff --git a/extensions/vscode-account/package.json b/extensions/vscode-account/package.json index 3a5407738c..ea3c2c2b89 100644 --- a/extensions/vscode-account/package.json +++ b/extensions/vscode-account/package.json @@ -51,9 +51,11 @@ "typescript": "^3.7.4", "tslint": "^5.12.1", "@types/node": "^10.12.21", - "@types/keytar": "^4.0.1" + "@types/keytar": "^4.0.1", + "@types/uuid": "^3.4.6" }, "dependencies": { + "uuid": "^3.3.3", "vscode-nls": "^4.1.1" } } diff --git a/extensions/vscode-account/src/AADHelper.ts b/extensions/vscode-account/src/AADHelper.ts index ec287d9bca..f232dfe99e 100644 --- a/extensions/vscode-account/src/AADHelper.ts +++ b/extensions/vscode-account/src/AADHelper.ts @@ -7,6 +7,7 @@ import * as crypto from 'crypto'; import * as https from 'https'; import * as querystring from 'querystring'; import * as vscode from 'vscode'; +import * as uuid from 'uuid'; import { createServer, startServer } from './authServer'; import { keychain } from './keychain'; import Logger from './logger'; @@ -81,7 +82,7 @@ export class AzureActiveDirectoryService { const sessions = this.parseStoredData(storedData); const refreshes = sessions.map(async session => { try { - await this.refreshToken(session.refreshToken, session.scope); + await this.refreshToken(session.refreshToken, session.scope, session.id); } catch (e) { if (e.message === REFRESH_NETWORK_FAILURE) { const didSucceedOnRetry = await this.handleRefreshNetworkError(session.id, session.refreshToken, session.scope); @@ -140,7 +141,7 @@ export class AzureActiveDirectoryService { const matchesExisting = this._tokens.some(token => token.scope === session.scope && token.sessionId === session.id); if (!matchesExisting) { try { - await this.refreshToken(session.refreshToken, session.scope); + await this.refreshToken(session.refreshToken, session.scope, session.id); addedIds.push(session.id); } catch (e) { if (e.message === REFRESH_NETWORK_FAILURE) { @@ -169,10 +170,17 @@ export class AzureActiveDirectoryService { } } else { if (this._tokens.length) { - // Log out all + // Log out all, remove all local data removedIds = this._tokens.map(token => token.sessionId); - Logger.info('No tokens in memory, clearing keychain data'); - await this.clearSessions(); + Logger.info('No stored keychain data, clearing local data'); + + this._tokens = []; + + this._refreshTimeouts.forEach(timeout => { + clearTimeout(timeout); + }); + + this._refreshTimeouts.clear(); } } @@ -203,7 +211,7 @@ export class AzureActiveDirectoryService { try { Logger.info('Token expired or unavailable, trying refresh'); - const refreshedToken = await this.refreshToken(token.refreshToken, token.scope); + const refreshedToken = await this.refreshToken(token.refreshToken, token.scope, token.sessionId); if (refreshedToken.accessToken) { return refreshedToken.accessToken; } else { @@ -379,7 +387,7 @@ export class AzureActiveDirectoryService { if (token.expiresIn) { this._refreshTimeouts.set(token.sessionId, setTimeout(async () => { try { - await this.refreshToken(token.refreshToken, scope); + await this.refreshToken(token.refreshToken, scope, token.sessionId); onDidChangeSessions.fire({ added: [], removed: [], changed: [token.sessionId] }); } catch (e) { if (e.message === REFRESH_NETWORK_FAILURE) { @@ -398,7 +406,7 @@ export class AzureActiveDirectoryService { this.storeTokenData(); } - private getTokenFromResponse(buffer: Buffer[], scope: string): IToken { + private getTokenFromResponse(buffer: Buffer[], scope: string, existingId?: string): IToken { const json = JSON.parse(Buffer.concat(buffer).toString()); const claims = this.getTokenClaims(json.access_token); return { @@ -407,7 +415,7 @@ export class AzureActiveDirectoryService { accessToken: json.access_token, refreshToken: json.refresh_token, scope, - sessionId: `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}/${scope}`, + sessionId: existingId || `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}/${uuid()}`, accountName: claims.email || claims.unique_name || 'user@example.com' }; } @@ -465,7 +473,7 @@ export class AzureActiveDirectoryService { }); } - private async refreshToken(refreshToken: string, scope: string): Promise { + private async refreshToken(refreshToken: string, scope: string, sessionId: string): Promise { return new Promise((resolve: (value: IToken) => void, reject) => { Logger.info('Refreshing token...'); const postData = querystring.stringify({ @@ -490,7 +498,7 @@ export class AzureActiveDirectoryService { }); result.on('end', async () => { if (result.statusCode === 200) { - const token = this.getTokenFromResponse(buffer, scope); + const token = this.getTokenFromResponse(buffer, scope, sessionId); this.setToken(token, scope); Logger.info('Token refresh success'); resolve(token); @@ -533,7 +541,7 @@ export class AzureActiveDirectoryService { this._refreshTimeouts.set(sessionId, setTimeout(async () => { try { - await this.refreshToken(refreshToken, scope); + await this.refreshToken(refreshToken, scope, sessionId); } catch (e) { this.pollForReconnect(sessionId, refreshToken, scope); } @@ -561,7 +569,7 @@ export class AzureActiveDirectoryService { this._refreshTimeouts.set(sessionId, setTimeout(async () => { try { - await this.refreshToken(refreshToken, scope); + await this.refreshToken(refreshToken, scope, sessionId); return resolve(true); } catch (e) { return resolve(await this.handleRefreshNetworkError(sessionId, refreshToken, scope, attempts + 1)); diff --git a/extensions/vscode-account/yarn.lock b/extensions/vscode-account/yarn.lock index 4a86ea6a2a..1506f62c87 100644 --- a/extensions/vscode-account/yarn.lock +++ b/extensions/vscode-account/yarn.lock @@ -30,6 +30,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg== +"@types/uuid@^3.4.6": + version "3.4.8" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.8.tgz#4ba887fcef88bd9a7515ca2de336d691e3e18318" + integrity sha512-zHWce3allXWSmRx6/AGXKCtSOA7JjeWd2L3t4aHfysNk8mouQnWCocveaT7a4IEIlPVHp81jzlnknqTgCjCLXA== + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -635,6 +640,11 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + vscode-nls@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" diff --git a/package.json b/package.json index 7ca29c04ec..d87c5c53d1 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "iconv-lite": "0.5.0", "jquery": "3.4.0", "jschardet": "2.1.1", - "keytar": "^4.11.0", + "keytar": "github:rmacfarlane/node-keytar#334424bd26414923782f144110f4beda19168d24", "minimist": "^1.2.5", "native-is-elevated": "0.4.1", "native-keymap": "2.1.1", @@ -185,7 +185,7 @@ "vinyl": "^2.0.0", "vinyl-fs": "^3.0.0", "vsce": "1.48.0", - "vscode-debugprotocol": "1.40.0-pre.1", + "vscode-debugprotocol": "^1.40.0", "vscode-nls-dev": "^3.3.1", "webpack": "^4.16.5", "webpack-cli": "^3.3.8", diff --git a/src/sql/workbench/contrib/queryHistory/browser/queryHistoryActions.ts b/src/sql/workbench/contrib/queryHistory/browser/queryHistoryActions.ts index 8f9adc25d7..dc9b2d84db 100644 --- a/src/sql/workbench/contrib/queryHistory/browser/queryHistoryActions.ts +++ b/src/sql/workbench/contrib/queryHistory/browser/queryHistoryActions.ts @@ -8,26 +8,29 @@ import { QUERY_HISTORY_PANEL_ID } from 'sql/workbench/contrib/queryHistory/commo import { RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { Action } from 'vs/base/common/actions'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; import { localize } from 'vs/nls'; import { IQueryHistoryService } from 'sql/workbench/services/queryHistory/common/queryHistoryService'; import { QueryHistoryNode } from 'sql/workbench/contrib/queryHistory/browser/queryHistoryNode'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { openNewQuery } from 'sql/workbench/contrib/query/browser/queryActions'; import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; -export class ToggleQueryHistoryAction extends TogglePanelAction { +export class ToggleQueryHistoryAction extends ToggleViewAction { public static readonly ID = 'workbench.action.tasks.toggleQueryHistory'; public static readonly LABEL = localize('toggleQueryHistory', "Toggle Query History"); constructor( id: string, label: string, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @IPanelService panelService: IPanelService, + @IViewsService viewsService: IViewsService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, QUERY_HISTORY_PANEL_ID, panelService, layoutService); + super(id, label, QUERY_HISTORY_PANEL_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); } } diff --git a/src/sql/workbench/contrib/tasks/browser/tasksActions.ts b/src/sql/workbench/contrib/tasks/browser/tasksActions.ts index b8edee2839..11b7b180bc 100644 --- a/src/sql/workbench/contrib/tasks/browser/tasksActions.ts +++ b/src/sql/workbench/contrib/tasks/browser/tasksActions.ts @@ -5,20 +5,23 @@ import { localize } from 'vs/nls'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; +import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { TASKS_PANEL_ID } from 'sql/workbench/contrib/tasks/common/tasks'; -export class ToggleTasksAction extends TogglePanelAction { +export class ToggleTasksAction extends ToggleViewAction { public static readonly ID = 'workbench.action.tasks.toggleTasks'; public static readonly LABEL = localize('toggleTasks', "Toggle Tasks"); constructor( id: string, label: string, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @IPanelService panelService: IPanelService, + @IViewsService viewsService: IViewsService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, TASKS_PANEL_ID, panelService, layoutService); + super(id, label, TASKS_PANEL_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); } } diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index b96ab3f508..59a686624b 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -159,6 +159,11 @@ export let addStandardDisposableGenericMouseDownListner = function addStandardDi return addDisposableGenericMouseDownListner(node, wrapHandler, useCapture); }; +export let addStandardDisposableGenericMouseUpListner = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable { + let wrapHandler = _wrapAsStandardMouseEvent(handler); + + return addDisposableGenericMouseUpListner(node, wrapHandler, useCapture); +}; export function addDisposableGenericMouseDownListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable { return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN, handler, useCapture); } diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg deleted file mode 100644 index 243be1451c..0000000000 --- a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg deleted file mode 100644 index 40ba72b708..0000000000 --- a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-hc.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg b/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg deleted file mode 100644 index 0d746558a4..0000000000 --- a/src/vs/base/browser/ui/breadcrumbs/tree-collapsed-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts index 074733483c..25934addfa 100644 --- a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts @@ -36,7 +36,7 @@ export class HorizontalScrollbar extends AbstractScrollbar { let scrollbarDelta = (options.horizontalScrollbarSize - ARROW_IMG_SIZE) / 2; this._createArrow({ - className: 'left-arrow', + className: 'scra codicon codicon-triangle-left', top: scrollbarDelta, left: arrowDelta, bottom: undefined, @@ -47,7 +47,7 @@ export class HorizontalScrollbar extends AbstractScrollbar { }); this._createArrow({ - className: 'right-arrow', + className: 'scra codicon codicon-triangle-right', top: scrollbarDelta, left: undefined, bottom: undefined, diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-down-dark.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-down-dark.svg deleted file mode 100644 index 23a6284928..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-down-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-down.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-down.svg deleted file mode 100644 index cf127c6a09..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-down.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-left-dark.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-left-dark.svg deleted file mode 100644 index 8a5909bb26..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-left-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-left.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-left.svg deleted file mode 100644 index d4f475e480..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-left.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-right-dark.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-right-dark.svg deleted file mode 100644 index 61dddd673c..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-right-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-right.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-right.svg deleted file mode 100644 index 824671db55..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-right.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-up-dark.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-up-dark.svg deleted file mode 100644 index 69a83f0f02..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-up-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/arrow-up.svg b/src/vs/base/browser/ui/scrollbar/media/arrow-up.svg deleted file mode 100644 index d2da965dee..0000000000 --- a/src/vs/base/browser/ui/scrollbar/media/arrow-up.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css index 044dc84808..cf885ab5fe 100644 --- a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css +++ b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css @@ -4,38 +4,9 @@ *--------------------------------------------------------------------------------------------*/ /* Arrows */ -.monaco-scrollable-element > .scrollbar > .up-arrow { - background: url('arrow-up.svg'); +.monaco-scrollable-element > .scrollbar > .scra { cursor: pointer; -} -.monaco-scrollable-element > .scrollbar > .down-arrow { - background: url('arrow-down.svg'); - cursor: pointer; -} -.monaco-scrollable-element > .scrollbar > .left-arrow { - background: url('arrow-left.svg'); - cursor: pointer; -} -.monaco-scrollable-element > .scrollbar > .right-arrow { - background: url('arrow-right.svg'); - cursor: pointer; -} - -.hc-black .monaco-scrollable-element > .scrollbar > .up-arrow, -.vs-dark .monaco-scrollable-element > .scrollbar > .up-arrow { - background: url('arrow-up-dark.svg'); -} -.hc-black .monaco-scrollable-element > .scrollbar > .down-arrow, -.vs-dark .monaco-scrollable-element > .scrollbar > .down-arrow { - background: url('arrow-down-dark.svg'); -} -.hc-black .monaco-scrollable-element > .scrollbar > .left-arrow, -.vs-dark .monaco-scrollable-element > .scrollbar > .left-arrow { - background: url('arrow-left-dark.svg'); -} -.hc-black .monaco-scrollable-element > .scrollbar > .right-arrow, -.vs-dark .monaco-scrollable-element > .scrollbar > .right-arrow { - background: url('arrow-right-dark.svg'); + font-size: 11px !important; } .monaco-scrollable-element > .visible { @@ -137,4 +108,4 @@ .hc-black .monaco-scrollable-element .shadow.top.left { box-shadow: none; -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts index 269d104660..a59e60bd50 100644 --- a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts @@ -37,7 +37,7 @@ export class VerticalScrollbar extends AbstractScrollbar { let scrollbarDelta = (options.verticalScrollbarSize - ARROW_IMG_SIZE) / 2; this._createArrow({ - className: 'up-arrow', + className: 'scra codicon codicon-triangle-up', top: arrowDelta, left: scrollbarDelta, bottom: undefined, @@ -48,7 +48,7 @@ export class VerticalScrollbar extends AbstractScrollbar { }); this._createArrow({ - className: 'down-arrow', + className: 'scra codicon codicon-triangle-down', top: undefined, left: scrollbarDelta, bottom: arrowDelta, diff --git a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts index 9ca0996221..02853ba2f2 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxNative.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxNative.ts @@ -52,6 +52,10 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate { })); }); + this._register(dom.addStandardDisposableListener(this.selectElement, 'click', (e) => { + dom.EventHelper.stop(e, true); + })); + this._register(dom.addStandardDisposableListener(this.selectElement, 'change', (e) => { this.selectElement.title = e.target.value; this._onDidSelect.fire({ diff --git a/src/vs/base/browser/ui/splitview/paneview.css b/src/vs/base/browser/ui/splitview/paneview.css index ccf4a96427..b69b232123 100644 --- a/src/vs/base/browser/ui/splitview/paneview.css +++ b/src/vs/base/browser/ui/splitview/paneview.css @@ -68,6 +68,24 @@ color: inherit; } +.monaco-pane-view .pane > .pane-header .monaco-action-bar .action-item.select-container { + cursor: default; +} + +.monaco-pane-view .pane > .pane-header .action-item .monaco-select-box { + cursor: pointer; + min-width: 110px; + min-height: 18px; + padding: 2px 23px 2px 8px; + background-color: inherit !important; + color: inherit !important; +} + +.linux .monaco-pane-view .pane > .pane-header .action-item .monaco-select-box, +.windows .monaco-pane-view .pane > .pane-header .action-item .monaco-select-box { + padding: 0px 23px 2px 8px; +} + /* Bold font style does not go well with CJK fonts */ .monaco-pane-view:lang(zh-Hans) .pane > .pane-header, .monaco-pane-view:lang(zh-Hant) .pane > .pane-header, diff --git a/src/vs/base/browser/ui/splitview/paneview.ts b/src/vs/base/browser/ui/splitview/paneview.ts index ef809c7f0a..a6818c561d 100644 --- a/src/vs/base/browser/ui/splitview/paneview.ts +++ b/src/vs/base/browser/ui/splitview/paneview.ts @@ -31,6 +31,7 @@ export interface IPaneStyles { headerForeground?: Color; headerBackground?: Color; headerBorder?: Color; + leftBorder?: Color; } /** @@ -243,6 +244,8 @@ export abstract class Pane extends Disposable implements IView { style(styles: IPaneStyles): void { this.styles = styles; + this.element.style.borderLeft = this.styles.leftBorder && this.orientation === Orientation.HORIZONTAL ? `1px solid ${this.styles.leftBorder}` : ''; + if (!this.header) { return; } @@ -261,7 +264,7 @@ export abstract class Pane extends Disposable implements IView { this.header.style.color = this.styles.headerForeground ? this.styles.headerForeground.toString() : ''; this.header.style.backgroundColor = this.styles.headerBackground ? this.styles.headerBackground.toString() : ''; - this.header.style.borderTop = this.styles.headerBorder ? `1px solid ${this.styles.headerBorder}` : ''; + this.header.style.borderTop = this.styles.headerBorder && this.orientation === Orientation.VERTICAL ? `1px solid ${this.styles.headerBorder}` : ''; this._dropBackground = this.styles.dropBackground; } diff --git a/src/vs/base/browser/ui/tree/media/loading-dark.svg b/src/vs/base/browser/ui/tree/media/loading-dark.svg deleted file mode 100644 index 7dc1ebd8cf..0000000000 --- a/src/vs/base/browser/ui/tree/media/loading-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/vs/base/browser/ui/tree/media/loading-hc.svg b/src/vs/base/browser/ui/tree/media/loading-hc.svg deleted file mode 100644 index c3633c0dda..0000000000 --- a/src/vs/base/browser/ui/tree/media/loading-hc.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/vs/base/browser/ui/tree/media/loading.svg b/src/vs/base/browser/ui/tree/media/loading.svg deleted file mode 100644 index e762f06d5e..0000000000 --- a/src/vs/base/browser/ui/tree/media/loading.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg deleted file mode 100644 index c2c2298dd5..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-collapsed-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg deleted file mode 100644 index 3732cbc04b..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-collapsed-hc.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg b/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg deleted file mode 100644 index 1952ad63f8..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-collapsed-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg deleted file mode 100644 index 5570923e17..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-expanded-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg deleted file mode 100644 index b370009330..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-expanded-hc.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg b/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg deleted file mode 100644 index 939ebc8b96..0000000000 --- a/src/vs/base/browser/ui/tree/media/tree-expanded-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/base/common/fuzzyScorer.ts b/src/vs/base/common/fuzzyScorer.ts index 290e05506f..44397e9ab3 100644 --- a/src/vs/base/common/fuzzyScorer.ts +++ b/src/vs/base/common/fuzzyScorer.ts @@ -4,56 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import { compareAnything } from 'vs/base/common/comparers'; -import { matchesPrefix, IMatch, matchesCamelCase, isUpper } from 'vs/base/common/filters'; +import { matchesPrefix, IMatch, matchesCamelCase, isUpper, fuzzyScore, createMatches as createFuzzyMatches } from 'vs/base/common/filters'; import { sep } from 'vs/base/common/path'; import { isWindows, isLinux } from 'vs/base/common/platform'; import { stripWildcards, equalsIgnoreCase } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; -import { distinctES6 } from 'vs/base/common/arrays'; -export type Score = [number /* score */, number[] /* match positions */]; -export type ScorerCache = { [key: string]: IItemScore }; +//#region Fuzzy scorer + +export type FuzzyScore = [number /* score */, number[] /* match positions */]; +export type FuzzyScorerCache = { [key: string]: IItemScore }; const NO_MATCH = 0; -const NO_SCORE: Score = [NO_MATCH, []]; +const NO_SCORE: FuzzyScore = [NO_MATCH, []]; // const DEBUG = false; // const DEBUG_MATRIX = false; -export function score(target: string, query: IPreparedQuery, fuzzy: boolean): Score { - if (query.values && query.values.length > 1) { - return scoreMultiple(target, query.values, fuzzy); - } - - return scoreSingle(target, query.normalized, query.normalizedLowercase, fuzzy); -} - -function scoreMultiple(target: string, query: IPreparedQueryPiece[], fuzzy: boolean): Score { - let totalScore = NO_MATCH; - const totalPositions: number[] = []; - - for (const { normalized, normalizedLowercase } of query) { - const [scoreValue, positions] = scoreSingle(target, normalized, normalizedLowercase, fuzzy); - if (scoreValue === NO_MATCH) { - // if a single query value does not match, return with - // no score entirely, we require all queries to match - return NO_SCORE; - } - - totalScore += scoreValue; - totalPositions.push(...positions); - } - - if (totalScore === NO_MATCH) { - return NO_SCORE; - } - - // if we have a score, ensure that the positions are - // sorted in ascending order and distinct - return [totalScore, distinctES6(totalPositions).sort((a, b) => a - b)]; -} - -function scoreSingle(target: string, query: string, queryLower: string, fuzzy: boolean): Score { +export function scoreFuzzy(target: string, query: string, queryLower: string, fuzzy: boolean): FuzzyScore { if (!target || !query) { return NO_SCORE; // return early if target or query are undefined } @@ -84,7 +52,7 @@ function scoreSingle(target: string, query: string, queryLower: string, fuzzy: b } } - const res = doScore(query, queryLower, queryLength, target, targetLower, targetLength); + const res = doScoreFuzzy(query, queryLower, queryLength, target, targetLower, targetLength); // if (DEBUG) { // console.log(`%cFinal Score: ${res[0]}`, 'font-weight: bold'); @@ -94,7 +62,7 @@ function scoreSingle(target: string, query: string, queryLower: string, fuzzy: b return res; } -function doScore(query: string, queryLower: string, queryLength: number, target: string, targetLower: string, targetLength: number): Score { +function doScoreFuzzy(query: string, queryLower: string, queryLength: number, target: string, targetLower: string, targetLength: number): FuzzyScore { const scores: number[] = []; const matches: number[] = []; @@ -291,6 +259,61 @@ function scoreSeparatorAtPos(charCode: number): number { // } // } +//#endregion + + +//#region Alternate fuzzy scorer implementation that is e.g. used for symbols + +export type FuzzyScore2 = [number /* score*/, IMatch[]]; + +const NO_SCORE2: FuzzyScore2 = [NO_MATCH, []]; + +export function scoreFuzzy2(target: string, query: IPreparedQuery, patternStart = 0, matchOffset = 0): FuzzyScore2 { + + // Score: multiple inputs + if (query.values && query.values.length > 1) { + return doScoreFuzzy2Multiple(target, query.values, patternStart, matchOffset); + } + + // Score: single input + return doScoreFuzzy2Single(target, query, patternStart, matchOffset); +} + +function doScoreFuzzy2Multiple(target: string, query: IPreparedQueryPiece[], patternStart: number, matchOffset: number): FuzzyScore2 { + let totalScore = 0; + const totalMatches: IMatch[] = []; + + for (const queryPiece of query) { + const [score, matches] = doScoreFuzzy2Single(target, queryPiece, patternStart, matchOffset); + if (!score) { + // if a single query value does not match, return with + // no score entirely, we require all queries to match + return NO_SCORE2; + } + + totalScore += score; + totalMatches.push(...matches); + } + + // if we have a score, ensure that the positions are + // sorted in ascending order and distinct + return [totalScore, normalizeMatches(totalMatches)]; +} + +function doScoreFuzzy2Single(target: string, query: IPreparedQueryPiece, patternStart: number, matchOffset: number): FuzzyScore2 { + const score = fuzzyScore(query.original, query.originalLowercase, patternStart, target, target.toLowerCase(), 0, true); + if (!score) { + return NO_SCORE2; + } + + return [score[0], createFuzzyMatches(score, matchOffset)]; +} + +//#endregion + + +//#region Item (label, description, path) scorer + /** * Scoring on structural items that have a label and optional description. */ @@ -337,99 +360,7 @@ const LABEL_PREFIX_SCORE = 1 << 17; const LABEL_CAMELCASE_SCORE = 1 << 16; const LABEL_SCORE_THRESHOLD = 1 << 15; -export interface IPreparedQueryPiece { - - /** - * The original query as provided as input. - */ - original: string; - originalLowercase: string; - - /** - * Original normalized to platform separators: - * - Windows: \ - * - Posix: / - */ - pathNormalized: string; - - /** - * In addition to the normalized path, will have - * whitespace and wildcards removed. - */ - normalized: string; - normalizedLowercase: string; -} - -export interface IPreparedQuery extends IPreparedQueryPiece { - - // Split by spaces - values: IPreparedQueryPiece[] | undefined; - - containsPathSeparator: boolean; -} - -/** - * Helper function to prepare a search value for scoring by removing unwanted characters - * and allowing to score on multiple pieces separated by whitespace character. - */ -const MULTIPL_QUERY_VALUES_SEPARATOR = ' '; -export function prepareQuery(original: string): IPreparedQuery { - if (typeof original !== 'string') { - original = ''; - } - - const originalLowercase = original.toLowerCase(); - const { pathNormalized, normalized, normalizedLowercase } = normalizeQuery(original); - const containsPathSeparator = pathNormalized.indexOf(sep) >= 0; - - let values: IPreparedQueryPiece[] | undefined = undefined; - - const originalSplit = original.split(MULTIPL_QUERY_VALUES_SEPARATOR); - if (originalSplit.length > 1) { - for (const originalPiece of originalSplit) { - const { - pathNormalized: pathNormalizedPiece, - normalized: normalizedPiece, - normalizedLowercase: normalizedLowercasePiece - } = normalizeQuery(originalPiece); - - if (normalizedPiece) { - if (!values) { - values = []; - } - - values.push({ - original: originalPiece, - originalLowercase: originalPiece.toLowerCase(), - pathNormalized: pathNormalizedPiece, - normalized: normalizedPiece, - normalizedLowercase: normalizedLowercasePiece - }); - } - } - } - - return { original, originalLowercase, pathNormalized, normalized, normalizedLowercase, values, containsPathSeparator }; -} - -function normalizeQuery(original: string): { pathNormalized: string, normalized: string, normalizedLowercase: string } { - let pathNormalized: string; - if (isWindows) { - pathNormalized = original.replace(/\//g, sep); // Help Windows users to search for paths when using slash - } else { - pathNormalized = original.replace(/\\/g, sep); // Help macOS/Linux users to search for paths when using backslash - } - - const normalized = stripWildcards(pathNormalized).replace(/\s/g, ''); - - return { - pathNormalized, - normalized, - normalizedLowercase: normalized.toLowerCase() - }; -} - -export function scoreItem(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache): IItemScore { +export function scoreItemFuzzy(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: FuzzyScorerCache): IItemScore { if (!item || !query.normalized) { return NO_ITEM_SCORE; // we need an item and query to score on at least } @@ -453,62 +384,86 @@ export function scoreItem(item: T, query: IPreparedQuery, fuzzy: boolean, acc return cached; } - const itemScore = doScoreItem(label, description, accessor.getItemPath(item), query, fuzzy); + const itemScore = doScoreItemFuzzy(label, description, accessor.getItemPath(item), query, fuzzy); cache[cacheHash] = itemScore; return itemScore; } -function createMatches(offsets: undefined | number[]): IMatch[] { - let ret: IMatch[] = []; - if (!offsets) { - return ret; - } +function doScoreItemFuzzy(label: string, description: string | undefined, path: string | undefined, query: IPreparedQuery, fuzzy: boolean): IItemScore { + const preferLabelMatches = !path || !query.containsPathSeparator; - let last: IMatch | undefined; - for (const pos of offsets) { - if (last && last.end === pos) { - last.end += 1; - } else { - last = { start: pos, end: pos + 1 }; - ret.push(last); - } - } - - return ret; -} - -function doScoreItem(label: string, description: string | undefined, path: string | undefined, query: IPreparedQuery, fuzzy: boolean): IItemScore { - - // 1.) treat identity matches on full path highest + // Treat identity matches on full path highest if (path && (isLinux ? query.pathNormalized === path : equalsIgnoreCase(query.pathNormalized, path))) { return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : undefined }; } - // We only consider label matches if the query is not including file path separators - const preferLabelMatches = !path || !query.containsPathSeparator; + // Score: multiple inputs + if (query.values && query.values.length > 1) { + return doScoreItemFuzzyMultiple(label, description, path, query.values, preferLabelMatches, fuzzy); + } + + // Score: single input + return doScoreItemFuzzySingle(label, description, path, query, preferLabelMatches, fuzzy); +} + +function doScoreItemFuzzyMultiple(label: string, description: string | undefined, path: string | undefined, query: IPreparedQueryPiece[], preferLabelMatches: boolean, fuzzy: boolean): IItemScore { + let totalScore = 0; + const totalLabelMatches: IMatch[] = []; + const totalDescriptionMatches: IMatch[] = []; + + for (const queryPiece of query) { + const { score, labelMatch, descriptionMatch } = doScoreItemFuzzySingle(label, description, path, queryPiece, preferLabelMatches, fuzzy); + if (score === NO_MATCH) { + // if a single query value does not match, return with + // no score entirely, we require all queries to match + return NO_ITEM_SCORE; + } + + totalScore += score; + if (labelMatch) { + totalLabelMatches.push(...labelMatch); + } + + if (descriptionMatch) { + totalDescriptionMatches.push(...descriptionMatch); + } + } + + // if we have a score, ensure that the positions are + // sorted in ascending order and distinct + return { + score: totalScore, + labelMatch: normalizeMatches(totalLabelMatches), + descriptionMatch: normalizeMatches(totalDescriptionMatches) + }; +} + +function doScoreItemFuzzySingle(label: string, description: string | undefined, path: string | undefined, query: IPreparedQueryPiece, preferLabelMatches: boolean, fuzzy: boolean): IItemScore { + + // Prefer label matches if told so if (preferLabelMatches) { - // 2.) treat prefix matches on the label second highest + // Treat prefix matches on the label second highest const prefixLabelMatch = matchesPrefix(query.normalized, label); if (prefixLabelMatch) { return { score: LABEL_PREFIX_SCORE, labelMatch: prefixLabelMatch }; } - // 3.) treat camelcase matches on the label third highest + // Treat camelcase matches on the label third highest const camelcaseLabelMatch = matchesCamelCase(query.normalized, label); if (camelcaseLabelMatch) { return { score: LABEL_CAMELCASE_SCORE, labelMatch: camelcaseLabelMatch }; } - // 4.) prefer scores on the label if any - const [labelScore, labelPositions] = score(label, query, fuzzy); + // Prefer scores on the label if any + const [labelScore, labelPositions] = scoreFuzzy(label, query.normalized, query.normalizedLowercase, fuzzy); if (labelScore) { return { score: labelScore + LABEL_SCORE_THRESHOLD, labelMatch: createMatches(labelPositions) }; } } - // 5.) finally compute description + label scores if we have a description + // Finally compute description + label scores if we have a description if (description) { let descriptionPrefix = description; if (!!path) { @@ -518,7 +473,7 @@ function doScoreItem(label: string, description: string | undefined, path: strin const descriptionPrefixLength = descriptionPrefix.length; const descriptionAndLabel = `${descriptionPrefix}${label}`; - const [labelDescriptionScore, labelDescriptionPositions] = score(descriptionAndLabel, query, fuzzy); + const [labelDescriptionScore, labelDescriptionPositions] = scoreFuzzy(descriptionAndLabel, query.normalized, query.normalizedLowercase, fuzzy); if (labelDescriptionScore) { const labelDescriptionMatches = createMatches(labelDescriptionPositions); const labelMatch: IMatch[] = []; @@ -551,9 +506,45 @@ function doScoreItem(label: string, description: string | undefined, path: strin return NO_ITEM_SCORE; } -export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache): number { - const itemScoreA = scoreItem(itemA, query, fuzzy, accessor, cache); - const itemScoreB = scoreItem(itemB, query, fuzzy, accessor, cache); +function createMatches(offsets: number[] | undefined): IMatch[] { + const ret: IMatch[] = []; + if (!offsets) { + return ret; + } + + let last: IMatch | undefined; + for (const pos of offsets) { + if (last && last.end === pos) { + last.end += 1; + } else { + last = { start: pos, end: pos + 1 }; + ret.push(last); + } + } + + return ret; +} + +function normalizeMatches(matches: IMatch[]): IMatch[] { + const positions = new Set(); + + for (const match of matches) { + for (let i = match.start; i < match.end; i++) { + positions.add(i); + } + } + + return createMatches(Array.from(positions.values()).sort((a, b) => a - b)); +} + +//#endregion + + +//#region Comparers + +export function compareItemsByFuzzyScore(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: FuzzyScorerCache): number { + const itemScoreA = scoreItemFuzzy(itemA, query, fuzzy, accessor, cache); + const itemScoreB = scoreItemFuzzy(itemB, query, fuzzy, accessor, cache); const scoreA = itemScoreA.score; const scoreB = itemScoreB.score; @@ -744,3 +735,112 @@ function fallbackCompare(itemA: T, itemB: T, query: IPreparedQuery, accessor: // equal return 0; } + +//#endregion + + +//#region Query Normalizer + +export interface IPreparedQueryPiece { + + /** + * The original query as provided as input. + */ + original: string; + originalLowercase: string; + + /** + * Original normalized to platform separators: + * - Windows: \ + * - Posix: / + */ + pathNormalized: string; + + /** + * In addition to the normalized path, will have + * whitespace and wildcards removed. + */ + normalized: string; + normalizedLowercase: string; +} + +export interface IPreparedQuery extends IPreparedQueryPiece { + + // Split by spaces + values: IPreparedQueryPiece[] | undefined; + + containsPathSeparator: boolean; +} + +/** + * Helper function to prepare a search value for scoring by removing unwanted characters + * and allowing to score on multiple pieces separated by whitespace character. + */ +const MULTIPLE_QUERY_VALUES_SEPARATOR = ' '; +export function prepareQuery(original: string): IPreparedQuery { + if (typeof original !== 'string') { + original = ''; + } + + const originalLowercase = original.toLowerCase(); + const { pathNormalized, normalized, normalizedLowercase } = normalizeQuery(original); + const containsPathSeparator = pathNormalized.indexOf(sep) >= 0; + + let values: IPreparedQueryPiece[] | undefined = undefined; + + const originalSplit = original.split(MULTIPLE_QUERY_VALUES_SEPARATOR); + if (originalSplit.length > 1) { + for (const originalPiece of originalSplit) { + const { + pathNormalized: pathNormalizedPiece, + normalized: normalizedPiece, + normalizedLowercase: normalizedLowercasePiece + } = normalizeQuery(originalPiece); + + if (normalizedPiece) { + if (!values) { + values = []; + } + + values.push({ + original: originalPiece, + originalLowercase: originalPiece.toLowerCase(), + pathNormalized: pathNormalizedPiece, + normalized: normalizedPiece, + normalizedLowercase: normalizedLowercasePiece + }); + } + } + } + + return { original, originalLowercase, pathNormalized, normalized, normalizedLowercase, values, containsPathSeparator }; +} + +function normalizeQuery(original: string): { pathNormalized: string, normalized: string, normalizedLowercase: string } { + let pathNormalized: string; + if (isWindows) { + pathNormalized = original.replace(/\//g, sep); // Help Windows users to search for paths when using slash + } else { + pathNormalized = original.replace(/\\/g, sep); // Help macOS/Linux users to search for paths when using backslash + } + + const normalized = stripWildcards(pathNormalized).replace(/\s/g, ''); + + return { + pathNormalized, + normalized, + normalizedLowercase: normalized.toLowerCase() + }; +} + +export function pieceToQuery(piece: IPreparedQueryPiece): IPreparedQuery; +export function pieceToQuery(pieces: IPreparedQueryPiece[]): IPreparedQuery; +export function pieceToQuery(arg1: IPreparedQueryPiece | IPreparedQueryPiece[]): IPreparedQuery { + if (Array.isArray(arg1)) { + return prepareQuery(arg1.map(piece => piece.original).join(MULTIPLE_QUERY_VALUES_SEPARATOR)); + } + + return prepareQuery(arg1.original); +} + +//#endregion diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index f130ef5930..92865c673d 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -113,6 +113,9 @@ export function mixin(destination: any, source: any, overwrite: boolean = true): return destination; } +/** + * @deprecated ES6 + */ export function assign(destination: T): T; export function assign(destination: T, u: U): T & U; export function assign(destination: T, u: U, v: V): T & U & V; diff --git a/src/vs/base/common/scrollable.ts b/src/vs/base/common/scrollable.ts index d36295a6c9..b3596e4aef 100644 --- a/src/vs/base/common/scrollable.ts +++ b/src/vs/base/common/scrollable.ts @@ -33,6 +33,9 @@ export interface ScrollEvent { export class ScrollState implements IScrollDimensions, IScrollPosition { _scrollStateBrand: void; + public readonly rawScrollLeft: number; + public readonly rawScrollTop: number; + public readonly width: number; public readonly scrollWidth: number; public readonly scrollLeft: number; @@ -55,6 +58,9 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { scrollHeight = scrollHeight | 0; scrollTop = scrollTop | 0; + this.rawScrollLeft = scrollLeft; // before validation + this.rawScrollTop = scrollTop; // before validation + if (width < 0) { width = 0; } @@ -85,7 +91,9 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { public equals(other: ScrollState): boolean { return ( - this.width === other.width + this.rawScrollLeft === other.rawScrollLeft + && this.rawScrollTop === other.rawScrollTop + && this.width === other.width && this.scrollWidth === other.scrollWidth && this.scrollLeft === other.scrollLeft && this.height === other.height @@ -98,10 +106,10 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { return new ScrollState( (typeof update.width !== 'undefined' ? update.width : this.width), (typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth), - this.scrollLeft, + this.rawScrollLeft, (typeof update.height !== 'undefined' ? update.height : this.height), (typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight), - this.scrollTop + this.rawScrollTop ); } @@ -109,10 +117,10 @@ export class ScrollState implements IScrollDimensions, IScrollPosition { return new ScrollState( this.width, this.scrollWidth, - (typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.scrollLeft), + (typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft), this.height, this.scrollHeight, - (typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.scrollTop) + (typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop) ); } diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index ebb26d44a2..4a42c9645b 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -5,45 +5,25 @@ import { URI, UriComponents } from 'vs/base/common/uri'; -const _typeof = { - number: 'number', - string: 'string', - undefined: 'undefined', - object: 'object', - function: 'function' -}; - /** * @returns whether the provided parameter is a JavaScript Array or not. */ export function isArray(array: any): array is any[] { - if (Array.isArray) { - return Array.isArray(array); - } - - if (array && typeof (array.length) === _typeof.number && array.constructor === Array) { - return true; - } - - return false; + return Array.isArray(array); } /** * @returns whether the provided parameter is a JavaScript String or not. */ export function isString(str: any): str is string { - if (typeof (str) === _typeof.string || str instanceof String) { - return true; - } - - return false; + return (typeof str === 'string'); } /** * @returns whether the provided parameter is a JavaScript Array and each element in the array is a string. */ export function isStringArray(value: any): value is string[] { - return isArray(value) && (value).every(elem => isString(elem)); + return Array.isArray(value) && (value).every(elem => isString(elem)); } /** @@ -55,7 +35,7 @@ export function isObject(obj: any): obj is Object { // The method can't do a type cast since there are type (like strings) which // are subclasses of any put not positvely matched by the function. Hence type // narrowing results in wrong results. - return typeof obj === _typeof.object + return typeof obj === 'object' && obj !== null && !Array.isArray(obj) && !(obj instanceof RegExp) @@ -67,32 +47,28 @@ export function isObject(obj: any): obj is Object { * @returns whether the provided parameter is a JavaScript Number or not. */ export function isNumber(obj: any): obj is number { - if ((typeof (obj) === _typeof.number || obj instanceof Number) && !isNaN(obj)) { - return true; - } - - return false; + return (typeof obj === 'number' && !isNaN(obj)); } /** * @returns whether the provided parameter is a JavaScript Boolean or not. */ export function isBoolean(obj: any): obj is boolean { - return obj === true || obj === false; + return (obj === true || obj === false); } /** * @returns whether the provided parameter is undefined. */ export function isUndefined(obj: any): obj is undefined { - return typeof (obj) === _typeof.undefined; + return (typeof obj === 'undefined'); } /** * @returns whether the provided parameter is undefined or null. */ export function isUndefinedOrNull(obj: any): obj is undefined | null { - return isUndefined(obj) || obj === null; + return (isUndefined(obj) || obj === null); } @@ -158,7 +134,7 @@ export function isEmptyObject(obj: any): obj is any { * @returns whether the provided parameter is a JavaScript Function or not. */ export function isFunction(obj: any): obj is Function { - return typeof obj === _typeof.function; + return (typeof obj === 'function'); } /** diff --git a/src/vs/base/parts/quickinput/browser/media/quickInput.css b/src/vs/base/parts/quickinput/browser/media/quickInput.css index dda4da8884..aca9fddc2d 100644 --- a/src/vs/base/parts/quickinput/browser/media/quickInput.css +++ b/src/vs/base/parts/quickinput/browser/media/quickInput.css @@ -237,11 +237,9 @@ .quick-input-list .quick-input-list-entry-action-bar .action-label { /* * By default, actions in the quick input action bar are hidden - * until hovered over them or selected. We do not use display:none - * so that the amount of visual flickering is little by reserving the - * space the button needs still. + * until hovered over them or selected. */ - visibility: hidden; + display: none; } .quick-input-list .quick-input-list-entry-action-bar .action-label.codicon { @@ -266,5 +264,5 @@ .quick-input-list .quick-input-list-entry .quick-input-list-entry-action-bar .action-label.always-visible, .quick-input-list .quick-input-list-entry:hover .quick-input-list-entry-action-bar .action-label, .quick-input-list .monaco-list-row.focused .quick-input-list-entry-action-bar .action-label { - visibility: visible; + display: flex; } diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 03aa842674..2832ed1710 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -386,7 +386,7 @@ class QuickPick extends QuickInput implements IQuickPi private _matchOnLabel = true; private _sortByLabel = true; private _autoFocusOnList = true; - private _itemActivation = ItemActivation.FIRST; + private _itemActivation = this.ui.isScreenReaderOptimized() ? ItemActivation.NONE /* https://github.com/microsoft/vscode/issues/57501 */ : ItemActivation.FIRST; private _activeItems: T[] = []; private activeItemsUpdated = false; private activeItemsToConfirm: T[] | null = []; @@ -637,7 +637,7 @@ class QuickPick extends QuickInput implements IQuickPi private trySelectFirst() { if (this.autoFocusOnList) { - if (!this.ui.isScreenReaderOptimized() && !this.canSelectMany) { + if (!this.canSelectMany) { this.ui.list.focus(QuickInputListFocus.First); } } @@ -683,22 +683,14 @@ class QuickPick extends QuickInput implements IQuickPi event.preventDefault(); break; case KeyCode.PageDown: - if (this.ui.list.getFocusedElements().length) { - this.ui.list.focus(QuickInputListFocus.NextPage); - } else { - this.ui.list.focus(QuickInputListFocus.First); - } + this.ui.list.focus(QuickInputListFocus.NextPage); if (this.canSelectMany) { this.ui.list.domFocus(); } event.preventDefault(); break; case KeyCode.PageUp: - if (this.ui.list.getFocusedElements().length) { - this.ui.list.focus(QuickInputListFocus.PreviousPage); - } else { - this.ui.list.focus(QuickInputListFocus.Last); - } + this.ui.list.focus(QuickInputListFocus.PreviousPage); if (this.canSelectMany) { this.ui.list.domFocus(); } @@ -875,6 +867,9 @@ class QuickPick extends QuickInput implements IQuickPi this.ui.visibleCount.setCount(this.ui.list.getVisibleCount()); this.ui.count.setCount(this.ui.list.getCheckedCount()); switch (this._itemActivation) { + case ItemActivation.NONE: + this._itemActivation = ItemActivation.FIRST; // only valid once, then unset + break; case ItemActivation.SECOND: this.ui.list.focus(QuickInputListFocus.Second); this._itemActivation = ItemActivation.FIRST; // only valid once, then unset @@ -1086,30 +1081,13 @@ export class QuickInputController extends Disposable { } private registerKeyModsListeners() { - this._register(dom.addDisposableListener(window, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { - const event = new StandardKeyboardEvent(e); - switch (event.keyCode) { - case KeyCode.Ctrl: - case KeyCode.Meta: - this.keyMods.ctrlCmd = true; - break; - case KeyCode.Alt: - this.keyMods.alt = true; - break; - } - })); - this._register(dom.addDisposableListener(window, dom.EventType.KEY_UP, (e: KeyboardEvent) => { - const event = new StandardKeyboardEvent(e); - switch (event.keyCode) { - case KeyCode.Ctrl: - case KeyCode.Meta: - this.keyMods.ctrlCmd = false; - break; - case KeyCode.Alt: - this.keyMods.alt = false; - break; - } - })); + const listener = (e: KeyboardEvent | MouseEvent) => { + this.keyMods.ctrlCmd = e.ctrlKey || e.metaKey; + this.keyMods.alt = e.altKey; + }; + this._register(dom.addDisposableListener(window, dom.EventType.KEY_DOWN, listener, true)); + this._register(dom.addDisposableListener(window, dom.EventType.KEY_UP, listener, true)); + this._register(dom.addDisposableListener(window, dom.EventType.MOUSE_DOWN, listener, true)); } private getUI() { @@ -1362,6 +1340,9 @@ export class QuickInputController extends Disposable { ]; input.canSelectMany = !!options.canPickMany; input.placeholder = options.placeHolder; + if (options.placeHolder) { + input.ariaLabel = options.placeHolder; + } input.ignoreFocusOut = !!options.ignoreFocusLost; input.matchOnDescription = !!options.matchOnDescription; input.matchOnDetail = !!options.matchOnDetail; diff --git a/src/vs/base/parts/quickinput/browser/quickInputList.ts b/src/vs/base/parts/quickinput/browser/quickInputList.ts index 8e931e1591..9d218cd6de 100644 --- a/src/vs/base/parts/quickinput/browser/quickInputList.ts +++ b/src/vs/base/parts/quickinput/browser/quickInputList.ts @@ -302,14 +302,12 @@ export class QuickInputList { } break; case KeyCode.UpArrow: - case KeyCode.PageUp: const focus1 = this.list.getFocus(); if (focus1.length === 1 && focus1[0] === 0) { this._onLeave.fire(); } break; case KeyCode.DownArrow: - case KeyCode.PageDown: const focus2 = this.list.getFocus(); if (focus2.length === 1 && focus2[0] === this.list.length - 1) { this._onLeave.fire(); @@ -518,11 +516,11 @@ export class QuickInputList { return; } - if ((what === QuickInputListFocus.Next || what === QuickInputListFocus.NextPage) && this.list.getFocus()[0] === this.list.length - 1) { + if (what === QuickInputListFocus.Next && this.list.getFocus()[0] === this.list.length - 1) { what = QuickInputListFocus.First; } - if ((what === QuickInputListFocus.Previous || what === QuickInputListFocus.PreviousPage) && this.list.getFocus()[0] === 0) { + if (what === QuickInputListFocus.Previous && this.list.getFocus()[0] === 0) { what = QuickInputListFocus.Last; } diff --git a/src/vs/base/parts/quickinput/common/quickInput.ts b/src/vs/base/parts/quickinput/common/quickInput.ts index 3ff9e35ebb..da1be68828 100644 --- a/src/vs/base/parts/quickinput/common/quickInput.ts +++ b/src/vs/base/parts/quickinput/common/quickInput.ts @@ -183,7 +183,8 @@ export interface IQuickPickAcceptEvent { } export enum ItemActivation { - FIRST = 1, + NONE, + FIRST, SECOND, LAST } @@ -326,7 +327,7 @@ export type QuickPickInput = T | IQuickPickSeparator; //region Fuzzy Scorer Support -export type IQuickPickItemWithResource = IQuickPickItem & { resource: URI | undefined }; +export type IQuickPickItemWithResource = IQuickPickItem & { resource?: URI }; export class QuickPickItemScorerAccessor implements IItemAccessor { diff --git a/src/vs/base/test/common/fuzzyScorer.test.ts b/src/vs/base/test/common/fuzzyScorer.test.ts index 945e4d9d24..b386809100 100644 --- a/src/vs/base/test/common/fuzzyScorer.test.ts +++ b/src/vs/base/test/common/fuzzyScorer.test.ts @@ -42,20 +42,28 @@ class NullAccessorClass implements scorer.IItemAccessor { } } -function _doScore(target: string, query: string, fuzzy: boolean): scorer.Score { - return scorer.score(target, scorer.prepareQuery(query), fuzzy); +function _doScore(target: string, query: string, fuzzy: boolean): scorer.FuzzyScore { + const preparedQuery = scorer.prepareQuery(query); + + return scorer.scoreFuzzy(target, preparedQuery.normalized, preparedQuery.normalizedLowercase, fuzzy); } -function scoreItem(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache): scorer.IItemScore { - return scorer.scoreItem(item, scorer.prepareQuery(query), fuzzy, accessor, cache); +function _doScore2(target: string, query: string): scorer.FuzzyScore2 { + const preparedQuery = scorer.prepareQuery(query); + + return scorer.scoreFuzzy2(target, preparedQuery); } -function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache): number { - return scorer.compareItemsByScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache); +function scoreItem(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.FuzzyScorerCache): scorer.IItemScore { + return scorer.scoreItemFuzzy(item, scorer.prepareQuery(query), fuzzy, accessor, cache); +} + +function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.FuzzyScorerCache): number { + return scorer.compareItemsByFuzzyScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache); } const NullAccessor = new NullAccessorClass(); -let cache: scorer.ScorerCache = Object.create(null); +let cache: scorer.FuzzyScorerCache = Object.create(null); suite('Fuzzy Scorer', () => { @@ -66,7 +74,7 @@ suite('Fuzzy Scorer', () => { test('score (fuzzy)', function () { const target = 'HeLlo-World'; - const scores: scorer.Score[] = []; + const scores: scorer.FuzzyScore[] = []; scores.push(_doScore(target, 'HelLo-World', true)); // direct case match scores.push(_doScore(target, 'hello-world', true)); // direct mix-case match scores.push(_doScore(target, 'HW', true)); // direct case prefix (multiple) @@ -109,42 +117,6 @@ suite('Fuzzy Scorer', () => { assert.equal(_doScore(target, 'eo', false)[0], 0); }); - test('score (fuzzy, multiple)', function () { - const target = 'HeLlo-World'; - - const [firstSingleScore, firstSinglePositions] = _doScore(target, 'HelLo', true); - const [secondSingleScore, secondSinglePositions] = _doScore(target, 'World', true); - const firstAndSecondSinglePositions = [...firstSinglePositions, ...secondSinglePositions]; - - let [multiScore, multiPositions] = _doScore(target, 'HelLo World', true); - - function assertScore() { - assert.ok(multiScore >= firstSingleScore + secondSingleScore); - for (let i = 0; i < multiPositions.length; i++) { - assert.equal(multiPositions[i], firstAndSecondSinglePositions[i]); - } - } - - function assertNoScore() { - assert.equal(multiScore, 0); - assert.equal(multiPositions.length, 0); - } - - assertScore(); - - [multiScore, multiPositions] = _doScore(target, 'World HelLo', true); - assertScore(); - - [multiScore, multiPositions] = _doScore(target, 'World HelLo World', true); - assertScore(); - - [multiScore, multiPositions] = _doScore(target, 'World HelLo Nothing', true); - assertNoScore(); - - [multiScore, multiPositions] = _doScore(target, 'More Nothing', true); - assertNoScore(); - }); - test('scoreItem - matches are proper', function () { let res = scoreItem(null, 'something', true, ResourceAccessor, cache); assert.ok(!res.score); @@ -217,6 +189,49 @@ suite('Fuzzy Scorer', () => { assert.ok(pathRes.score > noRes.score); }); + test('scoreItem - multiple', function () { + const resource = URI.file('/xyz/some/path/someFile123.txt'); + + let res1 = scoreItem(resource, 'xyz some', true, ResourceAccessor, cache); + assert.ok(res1.score); + assert.equal(res1.labelMatch?.length, 1); + assert.equal(res1.labelMatch![0].start, 0); + assert.equal(res1.labelMatch![0].end, 4); + assert.equal(res1.descriptionMatch?.length, 1); + assert.equal(res1.descriptionMatch![0].start, 1); + assert.equal(res1.descriptionMatch![0].end, 4); + + let res2 = scoreItem(resource, 'some xyz', true, ResourceAccessor, cache); + assert.ok(res2.score); + assert.equal(res1.score, res2.score); + assert.equal(res2.labelMatch?.length, 1); + assert.equal(res2.labelMatch![0].start, 0); + assert.equal(res2.labelMatch![0].end, 4); + assert.equal(res2.descriptionMatch?.length, 1); + assert.equal(res2.descriptionMatch![0].start, 1); + assert.equal(res2.descriptionMatch![0].end, 4); + + let res3 = scoreItem(resource, 'some xyz file file123', true, ResourceAccessor, cache); + assert.ok(res3.score); + assert.ok(res3.score > res2.score); + assert.equal(res3.labelMatch?.length, 1); + assert.equal(res3.labelMatch![0].start, 0); + assert.equal(res3.labelMatch![0].end, 11); + assert.equal(res3.descriptionMatch?.length, 1); + assert.equal(res3.descriptionMatch![0].start, 1); + assert.equal(res3.descriptionMatch![0].end, 4); + + let res4 = scoreItem(resource, 'path z y', true, ResourceAccessor, cache); + assert.ok(res4.score); + assert.ok(res4.score < res2.score); + assert.equal(res4.labelMatch?.length, 0); + assert.equal(res4.descriptionMatch?.length, 2); + assert.equal(res4.descriptionMatch![0].start, 2); + assert.equal(res4.descriptionMatch![0].end, 4); + assert.equal(res4.descriptionMatch![1].start, 10); + assert.equal(res4.descriptionMatch![1].end, 14); + }); + test('scoreItem - invalid input', function () { let res = scoreItem(null, null!, true, ResourceAccessor, cache); @@ -878,6 +893,11 @@ suite('Fuzzy Scorer', () => { assert.equal(query.values?.[1].normalized, 'World'); assert.equal(query.values?.[1].normalizedLowercase, 'World'.toLowerCase()); + let restoredQuery = scorer.pieceToQuery(query.values!); + assert.equal(restoredQuery.original, query.original); + assert.equal(restoredQuery.values?.length, query.values?.length); + assert.equal(restoredQuery.containsPathSeparator, query.containsPathSeparator); + // with spaces that are empty query = scorer.prepareQuery(' Hello World '); assert.equal(query.original, ' Hello World '); @@ -911,4 +931,48 @@ suite('Fuzzy Scorer', () => { assert.equal(scorer.prepareQuery('\\some\\path').containsPathSeparator, true); } }); + + test('fuzzyScore2 (multiple queries)', function () { + const target = 'HeLlo-World'; + + const [firstSingleScore, firstSingleMatches] = _doScore2(target, 'HelLo'); + const [secondSingleScore, secondSingleMatches] = _doScore2(target, 'World'); + const firstAndSecondSingleMatches = [...firstSingleMatches || [], ...secondSingleMatches || []]; + + let [multiScore, multiMatches] = _doScore2(target, 'HelLo World'); + + function assertScore() { + assert.ok(multiScore ?? 0 >= ((firstSingleScore ?? 0) + (secondSingleScore ?? 0))); + for (let i = 0; multiMatches && i < multiMatches.length; i++) { + const multiMatch = multiMatches[i]; + const firstAndSecondSingleMatch = firstAndSecondSingleMatches[i]; + + if (multiMatch && firstAndSecondSingleMatch) { + assert.equal(multiMatch.start, firstAndSecondSingleMatch.start); + assert.equal(multiMatch.end, firstAndSecondSingleMatch.end); + } else { + assert.fail(); + } + } + } + + function assertNoScore() { + assert.equal(multiScore, 0); + assert.equal(multiMatches.length, 0); + } + + assertScore(); + + [multiScore, multiMatches] = _doScore2(target, 'World HelLo'); + assertScore(); + + [multiScore, multiMatches] = _doScore2(target, 'World HelLo World'); + assertScore(); + + [multiScore, multiMatches] = _doScore2(target, 'World HelLo Nothing'); + assertNoScore(); + + [multiScore, multiMatches] = _doScore2(target, 'More Nothing'); + assertNoScore(); + }); }); diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 19baa090ad..ad7530b57c 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -704,6 +704,11 @@ export interface ICodeEditor extends editorCommon.IEditor { */ getVisibleRanges(): Range[]; + /** + * @internal + */ + getVisibleRangesPlusViewportAboveBelow(): Range[]; + /** * Get the view zones. * @internal diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 056d82d623..5006cc9eb4 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -460,6 +460,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return this._modelData.viewModel.getVisibleRanges(); } + public getVisibleRangesPlusViewportAboveBelow(): Range[] { + if (!this._modelData) { + return []; + } + return this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow(); + } + public getWhitespaces(): IEditorWhitespace[] { if (!this._modelData) { return []; diff --git a/src/vs/editor/common/model/tokensStore.ts b/src/vs/editor/common/model/tokensStore.ts index 92131cf7bf..fc82d18636 100644 --- a/src/vs/editor/common/model/tokensStore.ts +++ b/src/vs/editor/common/model/tokensStore.ts @@ -890,15 +890,18 @@ export class TokensStore2 { } public setPartial(_range: Range, pieces: MultilineTokens2[]): Range { - if (pieces.length === 0) { - return _range; + // console.log(`setPartial ${_range} ${pieces.map(p => p.toString()).join(', ')}`); + + let range = _range; + if (pieces.length > 0) { + const _firstRange = pieces[0].getRange(); + const _lastRange = pieces[pieces.length - 1].getRange(); + if (!_firstRange || !_lastRange) { + return _range; + } + range = _range.plusRange(_firstRange).plusRange(_lastRange); } - const _firstRange = pieces[0].getRange(); - const _lastRange = pieces[pieces.length - 1].getRange(); - if (!_firstRange || !_lastRange) { - return _range; - } - const range = _range.plusRange(_firstRange).plusRange(_lastRange); + let insertPosition: { index: number; } | null = null; for (let i = 0, len = this._pieces.length; i < len; i++) { const piece = this._pieces[i]; @@ -938,6 +941,15 @@ export class TokensStore2 { // after removal, this piece contains the range const [a, b] = piece.split(range); + if (a.isEmpty()) { + // this piece is actually after the range + insertPosition = insertPosition || { index: i }; + continue; + } + if (b.isEmpty()) { + // this piece is actually before the range + continue; + } this._pieces.splice(i, 1, a, b); i++; len++; @@ -947,10 +959,12 @@ export class TokensStore2 { insertPosition = insertPosition || { index: this._pieces.length }; - this._pieces = arrays.arrayInsert(this._pieces, insertPosition.index, pieces); + if (pieces.length > 0) { + this._pieces = arrays.arrayInsert(this._pieces, insertPosition.index, pieces); + } // console.log(`I HAVE ${this._pieces.length} pieces`); - // console.log(`${this._pieces.map(p => p.toString()).join(', ')}`); + // console.log(`${this._pieces.map(p => p.toString()).join('\n')}`); return range; } diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 3d1372e38c..73d894a28e 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -473,7 +473,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { const model = modelData.model; let maintainUndoRedoStack = false; let heapSize = 0; - if (MAINTAIN_UNDO_REDO_STACK && (resource.scheme === Schemas.file || resource.scheme === Schemas.vscodeRemote)) { + if (MAINTAIN_UNDO_REDO_STACK && (resource.scheme === Schemas.file || resource.scheme === Schemas.vscodeRemote || resource.scheme === Schemas.userData)) { const elements = this._undoRedoService.getElements(resource); if ((elements.past.length > 0 || elements.future.length > 0) && isEditStackPastFutureElements(elements)) { maintainUndoRedoStack = true; @@ -577,9 +577,17 @@ export interface ILineSequence { getLineContent(lineNumber: number): string; } -class SemanticColoringFeature extends Disposable { +export const SEMANTIC_HIGHLIGHTING_SETTING_ID = 'editor.semanticHighlighting'; - private static readonly SETTING_ID = 'editor.semanticHighlighting'; +export function isSemanticColoringEnabled(model: ITextModel, themeService: IThemeService, configurationService: IConfigurationService): boolean { + if (!themeService.getColorTheme().semanticHighlighting) { + return false; + } + const options = configurationService.getValue(SEMANTIC_HIGHLIGHTING_SETTING_ID, { overrideIdentifier: model.getLanguageIdentifier().language, resource: model.uri }); + return Boolean(options && options.enabled); +} + +class SemanticColoringFeature extends Disposable { private readonly _watchers: Record; private readonly _semanticStyling: SemanticStyling; @@ -589,13 +597,6 @@ class SemanticColoringFeature extends Disposable { this._watchers = Object.create(null); this._semanticStyling = semanticStyling; - const isSemanticColoringEnabled = (model: ITextModel) => { - if (!themeService.getColorTheme().semanticHighlighting) { - return false; - } - const options = configurationService.getValue(SemanticColoringFeature.SETTING_ID, { overrideIdentifier: model.getLanguageIdentifier().language, resource: model.uri }); - return options && options.enabled; - }; const register = (model: ITextModel) => { this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService, this._semanticStyling); }; @@ -606,7 +607,7 @@ class SemanticColoringFeature extends Disposable { const handleSettingOrThemeChange = () => { for (let model of modelService.getModels()) { const curr = this._watchers[model.uri.toString()]; - if (isSemanticColoringEnabled(model)) { + if (isSemanticColoringEnabled(model, themeService, configurationService)) { if (!curr) { register(model); } @@ -618,7 +619,7 @@ class SemanticColoringFeature extends Disposable { } }; this._register(modelService.onModelAdded((model) => { - if (isSemanticColoringEnabled(model)) { + if (isSemanticColoringEnabled(model, themeService, configurationService)) { register(model); } })); @@ -629,7 +630,7 @@ class SemanticColoringFeature extends Disposable { } })); this._register(configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(SemanticColoringFeature.SETTING_ID)) { + if (e.affectsConfiguration(SEMANTIC_HIGHLIGHTING_SETTING_ID)) { handleSettingOrThemeChange(); } })); diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 9f28720282..b6a5be0209 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -402,8 +402,26 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel this._updateConfigurationViewLineCount.schedule(); } + public getVisibleRangesPlusViewportAboveBelow(): Range[] { + const layoutInfo = this.configuration.options.get(EditorOption.layoutInfo); + const lineHeight = this.configuration.options.get(EditorOption.lineHeight); + const linesAround = Math.max(20, Math.round(layoutInfo.height / lineHeight)); + const partialData = this.viewLayout.getLinesViewportData(); + const startViewLineNumber = Math.max(1, partialData.completelyVisibleStartLineNumber - linesAround); + const endViewLineNumber = Math.min(this.getLineCount(), partialData.completelyVisibleEndLineNumber + linesAround); + + return this._toModelVisibleRanges(new Range( + startViewLineNumber, this.getLineMinColumn(startViewLineNumber), + endViewLineNumber, this.getLineMaxColumn(endViewLineNumber) + )); + } + public getVisibleRanges(): Range[] { const visibleViewRange = this.getCompletelyVisibleViewRange(); + return this._toModelVisibleRanges(visibleViewRange); + } + + private _toModelVisibleRanges(visibleViewRange: Range): Range[] { const visibleRange = this.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange); const hiddenAreas = this.lines.getHiddenAreas(); diff --git a/src/vs/editor/contrib/find/findWidget.ts b/src/vs/editor/contrib/find/findWidget.ts index 0164b77162..d2f405805d 100644 --- a/src/vs/editor/contrib/find/findWidget.ts +++ b/src/vs/editor/contrib/find/findWidget.ts @@ -924,7 +924,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas return null; } try { - new RegExp(value); + // use `g` and `u` which are also used by the TextModel search + new RegExp(value, 'gu'); return null; } catch (e) { return { content: e.message }; diff --git a/src/vs/editor/contrib/find/images/chevron-next-dark.svg b/src/vs/editor/contrib/find/images/chevron-next-dark.svg deleted file mode 100644 index dbe70d742d..0000000000 --- a/src/vs/editor/contrib/find/images/chevron-next-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/chevron-next-light.svg b/src/vs/editor/contrib/find/images/chevron-next-light.svg deleted file mode 100644 index ec824f41cc..0000000000 --- a/src/vs/editor/contrib/find/images/chevron-next-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/chevron-previous-dark.svg b/src/vs/editor/contrib/find/images/chevron-previous-dark.svg deleted file mode 100644 index 5db4f79da8..0000000000 --- a/src/vs/editor/contrib/find/images/chevron-previous-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/chevron-previous-light.svg b/src/vs/editor/contrib/find/images/chevron-previous-light.svg deleted file mode 100644 index aac3a5020c..0000000000 --- a/src/vs/editor/contrib/find/images/chevron-previous-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/close-dark.svg b/src/vs/editor/contrib/find/images/close-dark.svg deleted file mode 100644 index 75644595d1..0000000000 --- a/src/vs/editor/contrib/find/images/close-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/close-light.svg b/src/vs/editor/contrib/find/images/close-light.svg deleted file mode 100644 index cf5f28ca35..0000000000 --- a/src/vs/editor/contrib/find/images/close-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/find-selection-dark.svg b/src/vs/editor/contrib/find/images/find-selection-dark.svg deleted file mode 100644 index 6fc07d81a5..0000000000 --- a/src/vs/editor/contrib/find/images/find-selection-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/find-selection-light.svg b/src/vs/editor/contrib/find/images/find-selection-light.svg deleted file mode 100644 index 3608b15d29..0000000000 --- a/src/vs/editor/contrib/find/images/find-selection-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/replace-all-dark.svg b/src/vs/editor/contrib/find/images/replace-all-dark.svg deleted file mode 100644 index 07bd41a789..0000000000 --- a/src/vs/editor/contrib/find/images/replace-all-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/replace-all-light.svg b/src/vs/editor/contrib/find/images/replace-all-light.svg deleted file mode 100644 index cd3974fae7..0000000000 --- a/src/vs/editor/contrib/find/images/replace-all-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/replace-dark.svg b/src/vs/editor/contrib/find/images/replace-dark.svg deleted file mode 100644 index 5882b22c58..0000000000 --- a/src/vs/editor/contrib/find/images/replace-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/find/images/replace-light.svg b/src/vs/editor/contrib/find/images/replace-light.svg deleted file mode 100644 index 220f2aba40..0000000000 --- a/src/vs/editor/contrib/find/images/replace-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 59d8e36863..2124cf85f6 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -563,11 +563,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget { const disposables = new DisposableStore(); const actionsElement = dom.append(hoverElement, $('div.actions')); if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) { - const peekProblemLabel = nls.localize('peek problem', "Peek Problem"); - const peekProblemKeybinding = this._keybindingService.lookupKeybinding(NextMarkerAction.ID); - const peekProblemKeybindingLabel = peekProblemKeybinding && peekProblemKeybinding.getLabel(); disposables.add(this.renderAction(actionsElement, { - label: peekProblemKeybindingLabel ? nls.localize('titleAndKb', "{0} ({1})", peekProblemLabel, peekProblemKeybindingLabel) : peekProblemLabel, + label: nls.localize('peek problem', "Peek Problem"), commandId: NextMarkerAction.ID, run: () => { this.hide(); @@ -604,12 +601,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget { } })); - const quickFixLabel = nls.localize('quick fixes', "Quick Fix..."); - const quickFixKeybinding = this._keybindingService.lookupKeybinding(QuickFixAction.Id); - const quickFixKeybindingLabel = quickFixKeybinding && quickFixKeybinding.getLabel(); - disposables.add(this.renderAction(actionsElement, { - label: quickFixKeybindingLabel ? nls.localize('titleAndKb', "{0} ({1})", quickFixLabel, quickFixKeybindingLabel) : quickFixLabel, + label: nls.localize('quick fixes', "Quick Fix..."), commandId: QuickFixAction.Id, run: (target) => { showing = true; @@ -645,11 +638,9 @@ export class ModesContentHoverWidget extends ContentHoverWidget { dom.append(action, $(`span.icon.${actionOptions.iconClass}`)); } const label = dom.append(action, $('span')); - label.textContent = actionOptions.label; const keybinding = this._keybindingService.lookupKeybinding(actionOptions.commandId); - if (keybinding) { - label.title = `${actionOptions.label} (${keybinding.getLabel()})`; - } + const keybindingLabel = keybinding ? keybinding.getLabel() : null; + label.textContent = keybindingLabel ? `${actionOptions.label} (${keybindingLabel})` : actionOptions.label; return dom.addDisposableListener(actionContainer, dom.EventType.CLICK, e => { e.stopPropagation(); e.preventDefault(); diff --git a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts index a5dd05576f..f815500590 100644 --- a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts @@ -52,6 +52,11 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu // Re-create whenever the active editor changes disposables.add(this.onDidActiveTextEditorControlChange(() => { + + // Clear old + pickerDisposable.value = undefined; + + // Add new pickerDisposable.value = this.doProvide(picker, token); })); diff --git a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts index 17f433800f..46ac5a3140 100644 --- a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts @@ -15,14 +15,13 @@ import { DocumentSymbol, SymbolKinds, SymbolTag, DocumentSymbolProviderRegistry, import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel'; import { values } from 'vs/base/common/collections'; import { trim, format } from 'vs/base/common/strings'; -import { fuzzyScore, FuzzyScore, createMatches } from 'vs/base/common/filters'; -import { assign } from 'vs/base/common/objects'; -import { prepareQuery, IPreparedQuery } from 'vs/base/common/fuzzyScorer'; +import { prepareQuery, IPreparedQuery, pieceToQuery, scoreFuzzy2 } from 'vs/base/common/fuzzyScorer'; +import { IMatch } from 'vs/base/common/filters'; export interface IGotoSymbolQuickPickItem extends IQuickPickItem { kind: SymbolKind, index: number, - score?: FuzzyScore; + score?: number; range?: { decoration: IRange, selection: IRange } } @@ -37,7 +36,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit static PREFIX_BY_CATEGORY = `${AbstractGotoSymbolQuickAccessProvider.PREFIX}${AbstractGotoSymbolQuickAccessProvider.SCOPE_PREFIX}`; constructor(protected options?: IGotoSymbolQuickAccessProviderOptions) { - super(assign(options, { canAcceptInBackground: true })); + super({ ...options, canAcceptInBackground: true }); } protected provideWithoutTextEditor(picker: IQuickPick): IDisposable { @@ -204,12 +203,12 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit const filterBySymbolKind = query.original.indexOf(AbstractGotoSymbolQuickAccessProvider.SCOPE_PREFIX) === 0; const filterPos = filterBySymbolKind ? 1 : 0; - // Split between symbol and container query if separated by space + // Split between symbol and container query let symbolQuery: IPreparedQuery; let containerQuery: IPreparedQuery | undefined; if (query.values && query.values.length > 1) { - symbolQuery = prepareQuery(query.values[0].original); - containerQuery = prepareQuery(query.values[1].original); + symbolQuery = pieceToQuery(query.values[0]); // symbol: only match on first part + containerQuery = pieceToQuery(query.values.slice(1)); // container: match on all but first parts } else { symbolQuery = query; } @@ -220,69 +219,79 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit const symbol = symbols[index]; const symbolLabel = trim(symbol.name); + const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`; let containerLabel = symbol.containerName; - if (containerLabel && options?.extraContainerLabel) { - containerLabel = `${options.extraContainerLabel} • ${containerLabel}`; - } else { - containerLabel = options?.extraContainerLabel; - } - - let symbolScore: FuzzyScore | undefined = undefined; - let containerScore: FuzzyScore | undefined = undefined; - - let includeSymbol = true; - if (query.original.length > filterPos) { - - // Score by symbol - symbolScore = fuzzyScore(symbolQuery.original, symbolQuery.originalLowercase, filterPos, symbolLabel, symbolLabel.toLowerCase(), 0, true); - includeSymbol = !!symbolScore; - - // Score by container if specified - if (includeSymbol && containerQuery) { - if (containerLabel) { - containerScore = fuzzyScore(containerQuery.original, containerQuery.originalLowercase, filterPos, containerLabel, containerLabel.toLowerCase(), 0, true); - } - - includeSymbol = !!containerScore; + if (options?.extraContainerLabel) { + if (containerLabel) { + containerLabel = `${options.extraContainerLabel} • ${containerLabel}`; + } else { + containerLabel = options.extraContainerLabel; } } - if (includeSymbol) { - const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`; - const deprecated = symbol.tags && symbol.tags.indexOf(SymbolTag.Deprecated) >= 0; + let symbolScore: number | undefined = undefined; + let symbolMatches: IMatch[] | undefined = undefined; - filteredSymbolPicks.push({ - index, - kind: symbol.kind, - score: symbolScore, - label: symbolLabelWithIcon, - ariaLabel: localize('symbolsAriaLabel', "{0}, symbols picker", symbolLabel), - description: containerLabel, - highlights: deprecated ? undefined : { - label: createMatches(symbolScore, symbolLabelWithIcon.length - symbolLabel.length /* Readjust matches to account for codicons in label */), - description: createMatches(containerScore) - }, - range: { - selection: Range.collapseToStart(symbol.selectionRange), - decoration: symbol.range - }, - strikethrough: deprecated, - buttons: (() => { - const openSideBySideDirection = this.options?.openSideBySideDirection(); - if (!openSideBySideDirection) { - return undefined; - } + let containerScore: number | undefined = undefined; + let containerMatches: IMatch[] | undefined = undefined; - return [ - { - iconClass: openSideBySideDirection === 'right' ? 'codicon-split-horizontal' : 'codicon-split-vertical', - tooltip: openSideBySideDirection === 'right' ? localize('openToSide', "Open to the Side") : localize('openToBottom', "Open to the Bottom") - } - ]; - })() - }); + if (query.original.length > filterPos) { + + // Score by symbol + [symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, filterPos, symbolLabelWithIcon.length - symbolLabel.length /* Readjust matches to account for codicons in label */); + if (!symbolScore) { + continue; + } + + // Score by container if specified + if (containerQuery) { + if (containerLabel && containerQuery.original.length > 0) { + [containerScore, containerMatches] = scoreFuzzy2(containerLabel, containerQuery); + } + + if (!containerScore) { + continue; + } + + if (symbolScore) { + symbolScore += containerScore; // boost symbolScore by containerScore + } + } } + + const deprecated = symbol.tags && symbol.tags.indexOf(SymbolTag.Deprecated) >= 0; + + filteredSymbolPicks.push({ + index, + kind: symbol.kind, + score: symbolScore, + label: symbolLabelWithIcon, + ariaLabel: symbolLabel, + description: containerLabel, + highlights: deprecated ? undefined : { + label: symbolMatches, + description: containerMatches + }, + range: { + selection: Range.collapseToStart(symbol.selectionRange), + decoration: symbol.range + }, + strikethrough: deprecated, + buttons: (() => { + const openSideBySideDirection = this.options?.openSideBySideDirection(); + if (!openSideBySideDirection) { + return undefined; + } + + return [ + { + iconClass: openSideBySideDirection === 'right' ? 'codicon-split-horizontal' : 'codicon-split-vertical', + tooltip: openSideBySideDirection === 'right' ? localize('openToSide', "Open to the Side") : localize('openToBottom', "Open to the Bottom") + } + ]; + })() + }); } // Sort by score @@ -351,9 +360,9 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit } if (symbolA.score && symbolB.score) { - if (symbolA.score[0] > symbolB.score[0]) { + if (symbolA.score > symbolB.score) { return -1; - } else if (symbolA.score[0] < symbolB.score[0]) { + } else if (symbolA.score < symbolB.score) { return 1; } } diff --git a/src/vs/editor/contrib/suggest/suggest.ts b/src/vs/editor/contrib/suggest/suggest.ts index b19693cbe4..6d65b8481d 100644 --- a/src/vs/editor/contrib/suggest/suggest.ts +++ b/src/vs/editor/contrib/suggest/suggest.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { first } from 'vs/base/common/async'; -import { assign } from 'vs/base/common/objects'; import { onUnexpectedExternalError, canceled, isPromiseCanceledError } from 'vs/base/common/errors'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; @@ -98,7 +97,7 @@ export class CompletionItem { this.resolve = (token) => { if (!cached) { cached = Promise.resolve(resolveCompletionItem.call(provider, model, Position.lift(position), completion, token)).then(value => { - assign(completion, value); + Object.assign(completion, value); this.isResolved = true; }, err => { if (isPromiseCanceledError(err)) { diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index c33cda843a..ef3f61df41 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -734,6 +734,7 @@ registerEditorCommand(new SuggestCommand({ registerEditorCommand(new SuggestCommand({ id: 'insertBestCompletion', precondition: ContextKeyExpr.and( + EditorContextKeys.textInputFocus, ContextKeyExpr.equals('config.editor.tabCompletion', 'on'), WordContextKey.AtEnd, SuggestContext.Visible.toNegated(), @@ -753,6 +754,7 @@ registerEditorCommand(new SuggestCommand({ registerEditorCommand(new SuggestCommand({ id: 'insertNextSuggestion', precondition: ContextKeyExpr.and( + EditorContextKeys.textInputFocus, ContextKeyExpr.equals('config.editor.tabCompletion', 'on'), SuggestAlternatives.OtherSuggestions, SuggestContext.Visible.toNegated(), @@ -769,6 +771,7 @@ registerEditorCommand(new SuggestCommand({ registerEditorCommand(new SuggestCommand({ id: 'insertPrevSuggestion', precondition: ContextKeyExpr.and( + EditorContextKeys.textInputFocus, ContextKeyExpr.equals('config.editor.tabCompletion', 'on'), SuggestAlternatives.OtherSuggestions, SuggestContext.Visible.toNegated(), diff --git a/src/vs/editor/contrib/suggest/suggestModel.ts b/src/vs/editor/contrib/suggest/suggestModel.ts index 1779c97d7e..bec341a59f 100644 --- a/src/vs/editor/contrib/suggest/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/suggestModel.ts @@ -511,6 +511,8 @@ export class SuggestModel implements IDisposable { if (!suggestOptions.showFolders) { result.add(CompletionItemKind.Folder); } if (!suggestOptions.showTypeParameters) { result.add(CompletionItemKind.TypeParameter); } if (!suggestOptions.showSnippets) { result.add(CompletionItemKind.Snippet); } + if (!suggestOptions.showUsers) { result.add(CompletionItemKind.User); } + if (!suggestOptions.showIssues) { result.add(CompletionItemKind.Issue); } return result; } diff --git a/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts b/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts index fb3a23f970..36bfec1737 100644 --- a/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts +++ b/src/vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens.ts @@ -13,6 +13,9 @@ import { ITextModel } from 'vs/editor/common/model'; import { DocumentRangeSemanticTokensProviderRegistry, DocumentRangeSemanticTokensProvider, SemanticTokens } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; import { toMultilineTokens2, SemanticTokensProviderStyling } from 'vs/editor/common/services/semanticTokensProviderStyling'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { isSemanticColoringEnabled, SEMANTIC_HIGHLIGHTING_SETTING_ID } from 'vs/editor/common/services/modelServiceImpl'; class ViewportSemanticTokensContribution extends Disposable implements IEditorContribution { @@ -28,7 +31,9 @@ class ViewportSemanticTokensContribution extends Disposable implements IEditorCo constructor( editor: ICodeEditor, - @IModelService private readonly _modelService: IModelService + @IModelService private readonly _modelService: IModelService, + @IThemeService private readonly _themeService: IThemeService, + @IConfigurationService private readonly _configurationService: IConfigurationService ) { super(); this._editor = editor; @@ -49,6 +54,16 @@ class ViewportSemanticTokensContribution extends Disposable implements IEditorCo this._cancelAll(); this._tokenizeViewport.schedule(); })); + this._register(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(SEMANTIC_HIGHLIGHTING_SETTING_ID)) { + this._cancelAll(); + this._tokenizeViewport.schedule(); + } + })); + this._register(this._themeService.onDidColorThemeChange(() => { + this._cancelAll(); + this._tokenizeViewport.schedule(); + })); } private static _getSemanticColoringProvider(model: ITextModel): DocumentRangeSemanticTokensProvider | null { @@ -80,12 +95,15 @@ class ViewportSemanticTokensContribution extends Disposable implements IEditorCo if (model.hasSemanticTokens()) { return; } + if (!isSemanticColoringEnabled(model, this._themeService, this._configurationService)) { + return; + } const provider = ViewportSemanticTokensContribution._getSemanticColoringProvider(model); if (!provider) { return; } const styling = this._modelService.getSemanticTokensProviderStyling(provider); - const visibleRanges = this._editor.getVisibleRanges(); + const visibleRanges = this._editor.getVisibleRangesPlusViewportAboveBelow(); this._outstandingRequests = this._outstandingRequests.concat(visibleRanges.map(range => this._requestRange(model, range, provider, styling))); } diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 891eaa7dd5..f8e0608e6c 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -54,6 +54,7 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService'; import { StandaloneQuickInputServiceImpl } from 'vs/editor/standalone/browser/quickInput/standaloneQuickInputServiceImpl'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export interface IEditorOverrideServices { [index: string]: any; @@ -166,6 +167,8 @@ export module StaticServices { export const storageService = define(IStorageService, () => new InMemoryStorageService()); + export const storageSyncService = define(IStorageKeysSyncRegistryService, () => new StorageKeysSyncRegistryService()); + export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o))); } diff --git a/src/vs/editor/test/common/model/tokensStore.test.ts b/src/vs/editor/test/common/model/tokensStore.test.ts index cd9fc2386a..68da0772a1 100644 --- a/src/vs/editor/test/common/model/tokensStore.test.ts +++ b/src/vs/editor/test/common/model/tokensStore.test.ts @@ -323,4 +323,68 @@ suite('TokensStore', () => { assert.equal(lineTokens.getCount(), 3); }); + test('issue #94133: Semantic colors stick around when using (only) range provider', () => { + const store = new TokensStore2(); + + // setPartial: [1,1 -> 1,20] [(1,9-11)] + store.setPartial(new Range(1, 1, 1, 20), [ + new MultilineTokens2(1, new SparseEncodedTokens(new Uint32Array([ + 0, 9, 11, 1, + ]))) + ]); + + // setPartial: [1,1 -> 1,20], [] + store.setPartial(new Range(1, 1, 1, 20), []); + + const lineTokens = store.addSemanticTokens(1, new LineTokens(new Uint32Array([12, 1]), `enum Enum1 {`)); + assert.equal(lineTokens.getCount(), 1); + }); + + test('bug', () => { + function createTokens(str: string): MultilineTokens2 { + str = str.replace(/^\[\(/, ''); + str = str.replace(/\)\]$/, ''); + const strTokens = str.split('),('); + let result: number[] = []; + let firstLineNumber = 0; + for (const strToken of strTokens) { + const pieces = strToken.split(','); + const chars = pieces[1].split('-'); + const lineNumber = parseInt(pieces[0], 10); + const startChar = parseInt(chars[0], 10); + const endChar = parseInt(chars[1], 10); + if (firstLineNumber === 0) { + // this is the first line + firstLineNumber = lineNumber; + } + result.push(lineNumber - firstLineNumber, startChar, endChar, (lineNumber + startChar) % 13); + } + return new MultilineTokens2(firstLineNumber, new SparseEncodedTokens(new Uint32Array(result))); + } + + const store = new TokensStore2(); + // setPartial [36446,1 -> 36475,115] [(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35),(36470,38-46),(36473,25-35),(36473,36-51),(36474,28-33),(36474,36-49),(36474,50-58),(36475,35-53),(36475,54-62)] + store.setPartial( + new Range(36446, 1, 36475, 115), + [createTokens('[(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35),(36470,38-46),(36473,25-35),(36473,36-51),(36474,28-33),(36474,36-49),(36474,50-58),(36475,35-53),(36475,54-62)]')] + ); + // setPartial [36436,1 -> 36464,142] [(36437,33-37),(36437,38-42),(36437,47-57),(36437,58-67),(36438,35-53),(36438,54-62),(36440,24-29),(36440,33-46),(36440,47-53),(36442,25-35),(36442,36-50),(36443,30-39),(36443,42-46),(36443,47-53),(36443,54-58),(36443,63-73),(36443,74-84),(36443,87-91),(36443,92-98),(36443,101-105),(36443,106-112),(36443,113-119),(36444,28-37),(36444,38-42),(36444,47-57),(36444,58-75),(36444,80-95),(36444,96-105),(36445,35-53),(36445,54-62),(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62)] + store.setPartial( + new Range(36436, 1, 36464, 142), + [createTokens('[(36437,33-37),(36437,38-42),(36437,47-57),(36437,58-67),(36438,35-53),(36438,54-62),(36440,24-29),(36440,33-46),(36440,47-53),(36442,25-35),(36442,36-50),(36443,30-39),(36443,42-46),(36443,47-53),(36443,54-58),(36443,63-73),(36443,74-84),(36443,87-91),(36443,92-98),(36443,101-105),(36443,106-112),(36443,113-119),(36444,28-37),(36444,38-42),(36444,47-57),(36444,58-75),(36444,80-95),(36444,96-105),(36445,35-53),(36445,54-62),(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62)]')] + ); + // setPartial [36457,1 -> 36485,140] [(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35),(36470,38-46),(36473,25-35),(36473,36-51),(36474,28-33),(36474,36-49),(36474,50-58),(36475,35-53),(36475,54-62),(36477,28-32),(36477,33-37),(36477,42-52),(36477,53-69),(36478,32-36),(36478,37-41),(36478,46-56),(36478,57-74),(36479,32-36),(36479,37-41),(36479,46-56),(36479,57-76),(36480,32-36),(36480,37-41),(36480,46-56),(36480,57-68),(36481,32-36),(36481,37-41),(36481,46-56),(36481,57-68),(36482,39-57),(36482,58-66),(36484,34-38),(36484,39-45),(36484,46-50),(36484,55-65),(36484,66-82),(36484,86-97),(36484,98-102),(36484,103-109),(36484,111-124),(36484,125-133),(36485,39-57),(36485,58-66)] + store.setPartial( + new Range(36457, 1, 36485, 140), + [createTokens('[(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35),(36470,38-46),(36473,25-35),(36473,36-51),(36474,28-33),(36474,36-49),(36474,50-58),(36475,35-53),(36475,54-62),(36477,28-32),(36477,33-37),(36477,42-52),(36477,53-69),(36478,32-36),(36478,37-41),(36478,46-56),(36478,57-74),(36479,32-36),(36479,37-41),(36479,46-56),(36479,57-76),(36480,32-36),(36480,37-41),(36480,46-56),(36480,57-68),(36481,32-36),(36481,37-41),(36481,46-56),(36481,57-68),(36482,39-57),(36482,58-66),(36484,34-38),(36484,39-45),(36484,46-50),(36484,55-65),(36484,66-82),(36484,86-97),(36484,98-102),(36484,103-109),(36484,111-124),(36484,125-133),(36485,39-57),(36485,58-66)]')] + ); + // setPartial [36441,1 -> 36469,56] [(36442,25-35),(36442,36-50),(36443,30-39),(36443,42-46),(36443,47-53),(36443,54-58),(36443,63-73),(36443,74-84),(36443,87-91),(36443,92-98),(36443,101-105),(36443,106-112),(36443,113-119),(36444,28-37),(36444,38-42),(36444,47-57),(36444,58-75),(36444,80-95),(36444,96-105),(36445,35-53),(36445,54-62),(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35)] + store.setPartial( + new Range(36441, 1, 36469, 56), + [createTokens('[(36442,25-35),(36442,36-50),(36443,30-39),(36443,42-46),(36443,47-53),(36443,54-58),(36443,63-73),(36443,74-84),(36443,87-91),(36443,92-98),(36443,101-105),(36443,106-112),(36443,113-119),(36444,28-37),(36444,38-42),(36444,47-57),(36444,58-75),(36444,80-95),(36444,96-105),(36445,35-53),(36445,54-62),(36448,24-29),(36448,33-46),(36448,47-54),(36450,25-35),(36450,36-50),(36451,28-33),(36451,36-49),(36451,50-57),(36452,35-53),(36452,54-62),(36454,33-38),(36454,41-54),(36454,55-60),(36455,35-53),(36455,54-62),(36457,33-44),(36457,45-49),(36457,50-56),(36457,62-83),(36457,84-88),(36458,35-53),(36458,54-62),(36460,33-37),(36460,38-42),(36460,47-57),(36460,58-67),(36461,35-53),(36461,54-62),(36463,34-38),(36463,39-45),(36463,46-51),(36463,54-63),(36463,64-71),(36463,76-80),(36463,81-87),(36463,88-92),(36463,97-107),(36463,108-119),(36464,35-53),(36464,54-62),(36466,33-71),(36466,72-76),(36467,35-53),(36467,54-62),(36469,24-29),(36469,33-46),(36469,47-54),(36470,24-35)]')] + ); + + const lineTokens = store.addSemanticTokens(36451, new LineTokens(new Uint32Array([60, 1]), ` if (flags & ModifierFlags.Ambient) {`)); + assert.equal(lineTokens.getCount(), 7); + }); }); diff --git a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts index 1e79da292c..d0e0e7b28d 100644 --- a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts @@ -25,10 +25,10 @@ import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common export interface ICommandQuickPick extends IPickerQuickAccessItem { commandId: string; - commandAlias: string | undefined; + commandAlias?: string; } -export interface ICommandsQuickAccessOptions extends IPickerQuickAccessProviderOptions { +export interface ICommandsQuickAccessOptions extends IPickerQuickAccessProviderOptions { showAlias: boolean; } @@ -122,8 +122,8 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc const commandPick = filteredCommandPicks[i]; const keybinding = this.keybindingService.lookupKeybinding(commandPick.commandId); const ariaLabel = keybinding ? - localize('commandPickAriaLabelWithKeybinding', "{0}, {1}, commands picker", commandPick.label, keybinding.getAriaLabel()) : - localize('commandPickAriaLabel', "{0}, commands picker", commandPick.label); + localize('commandPickAriaLabelWithKeybinding', "{0}, {1}", commandPick.label, keybinding.getAriaLabel()) : + commandPick.label; // Separator: recently used if (i === 0 && this.commandsHistory.peek(commandPick.commandId)) { diff --git a/src/vs/platform/quickinput/browser/helpQuickAccess.ts b/src/vs/platform/quickinput/browser/helpQuickAccess.ts index a317bf1eb9..29ea72ca57 100644 --- a/src/vs/platform/quickinput/browser/helpQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/helpQuickAccess.ts @@ -77,7 +77,7 @@ export class HelpQuickAccessProvider implements IQuickAccessProvider { (helpEntry.needsEditor ? editorProviders : globalProviders).push({ prefix, label, - ariaLabel: localize('entryAriaLabel', "{0}, quick access help picker", label), + ariaLabel: localize('helpPickAriaLabel', "{0}, {1}", label, helpEntry.description), description: helpEntry.description }); } diff --git a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts index bc7773dde9..8ed2038951 100644 --- a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts @@ -59,8 +59,17 @@ export interface IPickerQuickAccessItem extends IQuickPickItem { trigger?(buttonIndex: number, keyMods: IKeyMods): TriggerAction | Promise; } -export interface IPickerQuickAccessProviderOptions { +export interface IPickerQuickAccessProviderOptions { + + /** + * Enables support for opening picks in the background via gesture. + */ canAcceptInBackground?: boolean; + + /** + * Enables to show a pick entry when no results are returned from a search. + */ + noResultsPick?: T; } export type Pick = T | IQuickPickSeparator; @@ -85,7 +94,7 @@ export abstract class PickerQuickAccessProvider) { super(); } @@ -113,9 +122,10 @@ export abstract class PickerQuickAccessProvider, skipEmpty?: boolean): boolean { + const applyPicks = (picks: Picks, skipEmpty?: boolean): boolean => { let items: ReadonlyArray>; let activeItem: T | undefined = undefined; @@ -126,8 +136,14 @@ export abstract class PickerQuickAccessProvider 0 && this.options?.noResultsPick) { + items = [this.options.noResultsPick]; + } } picker.items = items; @@ -136,7 +152,7 @@ export abstract class PickerQuickAccessProvider value.substring(descriptor ? descriptor.prefix.length : 0); + if (descriptor?.placeholder) { + picker.ariaLabel = descriptor?.placeholder; + } // Register listeners const cancellationToken = this.registerPickerListeners(picker, provider, descriptor, value, disposables); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0120b66a0e..7b0aaa49fe 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3164,7 +3164,7 @@ declare module 'vscode' { */ public readonly tokenModifiers: string[]; - constructor(tokenTypes: string[], tokenModifiers: string[]); + constructor(tokenTypes: string[], tokenModifiers?: string[]); } /** @@ -3184,7 +3184,7 @@ declare module 'vscode' { * @param tokenType The encoded token type. * @param tokenModifiers The encoded token modifiers. */ - push(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void; + push(line: number, char: number, length: number, tokenType: number, tokenModifiers?: number): void; /** * Add another token. Use only when providing a legend. @@ -3203,8 +3203,8 @@ declare module 'vscode' { /** * Represents semantic tokens, either in a range or in an entire document. - * See [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. - * See `SemanticTokensBuilder` for a helper to create an instance. + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to create an instance. */ export class SemanticTokens { /** @@ -3215,7 +3215,7 @@ declare module 'vscode' { readonly resultId?: string; /** * The actual tokens data. - * See [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens) for an explanation of the format. */ readonly data: Uint32Array; @@ -3224,7 +3224,7 @@ declare module 'vscode' { /** * Represents edits to semantic tokens. - * See [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. + * @see [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. */ export class SemanticTokensEdits { /** @@ -3244,7 +3244,7 @@ declare module 'vscode' { /** * Represents an edit to semantic tokens. - * See [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. + * @see [provideDocumentSemanticTokensEdits](#DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits) for an explanation of the format. */ export class SemanticTokensEdit { /** @@ -3274,11 +3274,8 @@ declare module 'vscode' { onDidChangeSemanticTokens?: Event; /** - * A file can contain many tokens, perhaps even hundreds of thousands of tokens. Therefore, to improve - * the memory consumption around describing semantic tokens, we have decided to avoid allocating an object - * for each token and we represent tokens from a file as an array of integers. Furthermore, the position - * of each token is expressed relative to the token before it because most tokens remain stable relative to - * each other when edits are made in a file. + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. * * --- * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: @@ -3331,6 +3328,7 @@ declare module 'vscode' { * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] * ``` * + * @see [SemanticTokensBuilder](#SemanticTokensBuilder) for a helper to encode tokens as integers. * *NOTE*: When doing edits, it is possible that multiple edits occur until VS Code decides to invoke the semantic tokens provider. * *NOTE*: If the provider cannot temporarily compute semantic tokens, it can indicate this by throwing an error with the message 'Busy'. */ @@ -3338,21 +3336,18 @@ declare module 'vscode' { /** * Instead of always returning all the tokens in a file, it is possible for a `DocumentSemanticTokensProvider` to implement - * this method (`updateSemanticTokens`) and then return incremental updates to the previously provided semantic tokens. + * this method (`provideDocumentSemanticTokensEdits`) and then return incremental updates to the previously provided semantic tokens. * * --- * ### How tokens change when the document changes * - * Let's look at how tokens might change. + * Suppose that `provideDocumentSemanticTokens` has previously returned the following semantic tokens: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` * - * Continuing with the above example, suppose a new line was inserted at the top of the file. - * That would make all the tokens move down by one line (notice how the line has changed for each one): - * ``` - * { line: 3, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, - * { line: 3, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, - * { line: 6, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } - * ``` - * The integer encoding of the tokens does not change substantially because of the delta-encoding of positions: + * Also suppose that after some edits, the new semantic tokens in a file are: * ``` * // 1st token, 2nd token, 3rd token * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] @@ -3365,26 +3360,6 @@ declare module 'vscode' { * edit: { start: 0, deleteCount: 1, data: [3] } // replace integer at offset 0 with 3 * ``` * - * Furthermore, let's assume that a new token has appeared on line 4: - * ``` - * { line: 3, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, - * { line: 3, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, - * { line: 4, startChar: 3, length: 5, tokenType: "property", tokenModifiers: ["static"] }, - * { line: 6, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } - * ``` - * The integer encoding of the tokens is: - * ``` - * // 1st token, 2nd token, 3rd token, 4th token - * [ 3,5,3,0,3, 0,5,4,1,0, 1,3,5,0,2, 2,2,7,2,0, ] - * ``` - * Again, it is possible to express these new tokens in terms of an edit applied to the previous tokens: - * ``` - * [ 3,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] // old tokens - * [ 3,5,3,0,3, 0,5,4,1,0, 1,3,5,0,2, 2,2,7,2,0, ] // new tokens - * - * edit: { start: 10, deleteCount: 1, data: [1,3,5,0,2,2] } // replace integer at offset 10 with [1,3,5,0,2,2] - * ``` - * * *NOTE*: If the provider cannot compute `SemanticTokensEdits`, it can "give up" and return all the tokens in the document again. * *NOTE*: All edits in `SemanticTokensEdits` contain indices in the old integers array, so they all refer to the previous result state. */ @@ -3397,7 +3372,7 @@ declare module 'vscode' { */ export interface DocumentRangeSemanticTokensProvider { /** - * See [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens). + * @see [provideDocumentSemanticTokens](#DocumentSemanticTokensProvider.provideDocumentSemanticTokens). */ provideDocumentRangeSemanticTokens(document: TextDocument, range: Range, token: CancellationToken): ProviderResult; } @@ -5233,6 +5208,9 @@ declare module 'vscode' { * [`Command`](#Command) or identifier of a command to run on click. * * The command must be [known](#commands.getCommands). + * + * Note that if this is a [`Command`](#Command) object, only the [`command`](#Command.command) and [`arguments`](#Command.arguments) + * are used by VS Code. */ command: string | Command | undefined; @@ -6840,9 +6818,6 @@ declare module 'vscode' { * Text based custom editors use a [`TextDocument`](#TextDocument) as their data model. This considerably simplifies * implementing a custom editor as it allows VS Code to handle many common operations such as * undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`. - * - * You should use text based custom editors when dealing with text based file formats, such as `xml` or `json`. - * For binary files or more specialized use cases, see [CustomEditorProvider](#CustomEditorProvider). */ export interface CustomTextEditorProvider { @@ -6865,259 +6840,6 @@ declare module 'vscode' { resolveCustomTextEditor(document: TextDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable | void; } - /** - * Defines the editing capability of a custom editor. This allows the custom editor to hook into standard - * editor events such as `undo` or `save`. - * - * @param EditType Type of edits used for the documents this delegate handles. - */ - interface CustomEditorEditingDelegate { - /** - * Save the resource. - * - * @param document Document to save. - * @param cancellation Token that signals the save is no longer required (for example, if another save was triggered). - * - * @return Thenable signaling that the save has completed. - */ - save(document: CustomDocument, cancellation: CancellationToken): Thenable; - - /** - * Save the existing resource at a new path. - * - * @param document Document to save. - * @param targetResource Location to save to. - * - * @return Thenable signaling that the save has completed. - */ - saveAs(document: CustomDocument, targetResource: Uri): Thenable; - - /** - * Event triggered by extensions to signal to VS Code that an edit has occurred. - */ - readonly onDidEdit: Event>; - - /** - * Apply a set of edits. - * - * Note that is not invoked when `onDidEdit` is called because `onDidEdit` implies also updating the view to reflect the edit. - * - * @param document Document to apply edits to. - * @param edit Array of edits. Sorted from oldest to most recent. - * - * @return Thenable signaling that the change has completed. - */ - applyEdits(document: CustomDocument, edits: ReadonlyArray): Thenable; - - /** - * Undo a set of edits. - * - * This is triggered when a user undoes an edit. - * - * @param document Document to undo edits from. - * @param edit Array of edits. Sorted from most recent to oldest. - * - * @return Thenable signaling that the change has completed. - */ - undoEdits(document: CustomDocument, edits: ReadonlyArray): Thenable; - - /** - * Revert the file to its last saved state. - * - * @param document Document to revert. - * @param edits Added or applied edits. - * - * @return Thenable signaling that the change has completed. - */ - revert(document: CustomDocument, edits: CustomDocumentRevert): Thenable; - - /** - * Back up the resource in its current state. - * - * Backups are used for hot exit and to prevent data loss. Your `backup` method should persist the resource in - * its current state, i.e. with the edits applied. Most commonly this means saving the resource to disk in - * the `ExtensionContext.storagePath`. When VS Code reloads and your custom editor is opened for a resource, - * your extension should first check to see if any backups exist for the resource. If there is a backup, your - * extension should load the file contents from there instead of from the resource in the workspace. - * - * `backup` is triggered whenever an edit it made. Calls to `backup` are debounced so that if multiple edits are - * made in quick succession, `backup` is only triggered after the last one. `backup` is not invoked when - * `auto save` is enabled (since auto save already persists resource ). - * - * @param document Document to backup. - * @param cancellation Token that signals the current backup since a new backup is coming in. It is up to your - * extension to decided how to respond to cancellation. If for example your extension is backing up a large file - * in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather - * than cancelling it to ensure that VS Code has some valid backup. - */ - backup(document: CustomDocument, cancellation: CancellationToken): Thenable; - } - - /** - * Event triggered by extensions to signal to VS Code that an edit has occurred on a `CustomDocument`. - * - * @param EditType Type of edits used for the document. - */ - interface CustomDocumentEditEvent { - /** - * Document the edit is for. - */ - readonly document: CustomDocument; - - /** - * Object that describes the edit. - * - * Edit objects are passed back to your extension in `CustomEditorEditingDelegate.undoEdits`, - * `CustomEditorEditingDelegate.applyEdits`, and `CustomEditorEditingDelegate.revert`. - */ - readonly edit: EditType; - - /** - * Display name describing the edit. - */ - readonly label?: string; - } - - /** - * Delta for edits undone/redone while reverting for a `CustomDocument`. - * - * @param EditType Type of edits used for the document being reverted. - */ - interface CustomDocumentRevert { - /** - * List of edits that were undone to get the document back to its on disk state. - */ - readonly undoneEdits: ReadonlyArray; - - /** - * List of edits that were reapplied to get the document back to its on disk state. - */ - readonly appliedEdits: ReadonlyArray; - } - - /** - * Represents a custom document used by a [`CustomEditorProvider`](#CustomEditorProvider). - * - * All custom documents must subclass `CustomDocument`. Custom documents are only used within a given - * `CustomEditorProvider`. The lifecycle of a `CustomDocument` is managed by VS Code. When no more references - * remain to a `CustomDocument`, it is disposed of. - * - * @param EditType Type of edits used in this document. - */ - class CustomDocument { - /** - * @param uri The associated resource for this document. - */ - constructor(uri: Uri); - - /** - * The associated uri for this document. - */ - readonly uri: Uri; - - /** - * Is this document representing an untitled file which has never been saved yet. - */ - readonly isUntitled: boolean; - - /** - * The version number of this document (it will strictly increase after each - * change, including undo/redo). - */ - readonly version: number; - - /** - * `true` if there are unpersisted changes. - */ - readonly isDirty: boolean; - - /** - * List of edits from document open to the document's current state. - * - * `appliedEdits` returns a copy of the edit stack at the current point in time. Your extension should always - * use `CustomDocument.appliedEdits` to check the edit stack instead of holding onto a reference to `appliedEdits`. - */ - readonly appliedEdits: ReadonlyArray; - - /** - * List of edits from document open to the document's last saved point. - * - * The save point will be behind `appliedEdits` if the user saves and then continues editing, - * or in front of the last entry in `appliedEdits` if the user saves and then hits undo. - * - * `savedEdits` returns a copy of the edit stack at the current point in time. Your extension should always - * use `CustomDocument.savedEdits` to check the edit stack instead of holding onto a reference to `savedEdits`. - */ - readonly savedEdits: ReadonlyArray; - - /** - * `true` if the document has been closed. A closed document isn't synchronized anymore - * and won't be reused when the same resource is opened again. - */ - readonly isClosed: boolean; - - /** - * Event fired when there are no more references to the `CustomDocument`. - * - * This happens when all custom editors for the document have been closed. Once a `CustomDocument` is disposed, - * it will not be reused when the same resource is opened again. - */ - readonly onDidDispose: Event; - } - - /** - * Provider for custom editors that use a custom document model. - * - * Custom editors use [`CustomDocument`](#CustomDocument) as their document model instead of a [`TextDocument`](#TextDocument). - * This gives extensions full control over actions such as edit, save, and backup. - * - * You should use this type of custom editor when dealing with binary files or more complex scenarios. For simple - * text based documents, use [`CustomTextEditorProvider`](#CustomTextEditorProvider) instead. - * - * @param EditType Type of edits used by the editors of this provider. - */ - export interface CustomEditorProvider { - - /** - * Create a new document for a given resource. - * - * `openCustomDocument` is called when the first editor for a given resource is opened, and the resolve document - * is passed to `resolveCustomEditor`. The resolved `CustomDocument` is re-used for subsequent editor opens. - * If all editors for a given resource are closed, the `CustomDocument` is disposed of. Opening an editor at - * this point will trigger another call to `openCustomDocument`. - * - * @param uri Uri of the document to open. - * @param token A cancellation token that indicates the result is no longer needed. - * - * @return The custom document. - */ - openCustomDocument(uri: Uri, token: CancellationToken): Thenable> | CustomDocument; - - /** - * Resolve a custom editor for a given resource. - * - * This is called whenever the user opens a new editor for this `CustomEditorProvider`. - * - * To resolve a custom editor, the provider must fill in its initial html content and hook up all - * the event listeners it is interested it. The provider can also hold onto the `WebviewPanel` to use later, - * for example in a command. See [`WebviewPanel`](#WebviewPanel) for additional details. - * - * @param document Document for the resource being resolved. - * @param webviewPanel Webview to resolve. - * @param token A cancellation token that indicates the result is no longer needed. - * - * @return Optional thenable indicating that the custom editor has been resolved. - */ - resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable | void; - - /** - * Defines the editing capability of the provider. - * - * When not provided, editors for this provider are considered readonly. - */ - readonly editingDelegate?: CustomEditorEditingDelegate; - } - /** * The clipboard provides read and write access to the system's clipboard. */ @@ -7956,22 +7678,19 @@ declare module 'vscode' { export function registerWebviewPanelSerializer(viewType: string, serializer: WebviewPanelSerializer): Disposable; /** - * Register a new provider for a custom editor. + * Register a provider for custom editors for the `viewType` contributed by the `customEditors` extension point. * - * @param viewType Type of the custom editor provider. This should match the `viewType` from the - * `package.json` contributions. + * When a custom editor is opened, VS Code fires an `onCustomEditor:viewType` activation event. Your extension + * must register a [`CustomTextEditorProvider`](#CustomTextEditorProvider) for `viewType` as part of activation. + * + * @param viewType Unique identifier for the custom editor provider. This should match the `viewType` from the + * `customEditors` contribution point. * @param provider Provider that resolves custom editors. * @param options Options for the provider. * * @return Disposable that unregisters the provider. */ - export function registerCustomEditorProvider( - viewType: string, - provider: CustomEditorProvider | CustomTextEditorProvider, - options?: { - readonly webviewOptions?: WebviewPanelOptions; - } - ): Disposable; + export function registerCustomEditorProvider(viewType: string, provider: CustomTextEditorProvider, options?: { readonly webviewOptions?: WebviewPanelOptions; }): Disposable; } /** @@ -9861,6 +9580,12 @@ declare module 'vscode' { /** * Register a semantic tokens provider for a document range. * + * *Note:* If a document has both a `DocumentSemanticTokensProvider` and a `DocumentRangeSemanticTokensProvider`, + * the range provider will be invoked only initially, for the time in which the full document provider takes + * to resolve the first request. Once the full document provider resolves the first request, the semantic tokens + * provided via the range provider will be discarded and from that point forward, only the document provider + * will be used. + * * Multiple providers can be registered for a language. In that case providers are sorted * by their [score](#languages.match) and the best-matching provider is used. Failure * of the selected provider will cause a failure of the whole operation. diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5152315479..fd82905e6d 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1182,6 +1182,330 @@ declare module 'vscode' { //#endregion + //#region Custom editor https://github.com/microsoft/vscode/issues/77131 + + /** + * Implements the editing functionality of a custom editor. + * + * This delegate is how custom editors hook into standard VS Code operations such as save and undo. The delegate + * is also how custom editors notify VS Code that an edit has taken place. + * + * @param EditType Type of edits used for the documents this delegate handles. + */ + interface CustomEditorEditingDelegate { + /** + * Save the resource for a custom editor. + * + * This method is invoked by VS Code when the user saves a custom editor. This can happen when the user + * triggers save while the custom editor is active, by commands such as `save all`, or by auto save if enabled. + * + * To implement `save`, the delegate must persist the custom editor. This usually means writing the + * file data for the custom document to disk. After `save` completes, any associated editor instances will + * no longer be marked as dirty. + * + * @param document Document to save. + * @param cancellation Token that signals the save is no longer required (for example, if another save was triggered). + * + * @return Thenable signaling that saving has completed. + */ + save(document: CustomDocument, cancellation: CancellationToken): Thenable; + + /** + * Save the resource for a custom editor to a different location. + * + * This method is invoked by VS Code when the user triggers `save as` on a custom editor. + * + * To implement `saveAs`, the delegate must persist the custom editor to `targetResource`. The + * existing editor will remain open after `saveAs` completes. + * + * @param document Document to save. + * @param targetResource Location to save to. + * @param cancellation Token that signals the save is no longer required. + * + * @return Thenable signaling that saving has completed. + */ + saveAs(document: CustomDocument, targetResource: Uri, cancellation: CancellationToken): Thenable; + + /** + * Signal that an edit has occurred inside a custom editor. + * + * This event must be fired by your extension whenever an edit happens in a custom editor. An edit can be + * anything from changing some text, to cropping an image, to reordering a list. Your extension is free to + * define what an edit is and what data is stored on each edit. + * + * VS Code uses edits to determine if a custom editor is dirty or not. VS Code also passes the edit objects back + * to your extension when triggers undo, redo, or revert (using the `undoEdits`, `applyEdits`, and `revert` + * methods of `CustomEditorEditingDelegate`) + */ + readonly onDidEdit: Event>; + + /** + * Apply a list of edits to a custom editor. + * + * This method is invoked by VS Code when the user triggers `redo` in a custom editor. + * + * To implement `applyEdits`, the delegate must make sure all editor instances (webviews) for `document` + * are updated to render the document's new state (that is, every webview must be updated to show the document + * after applying `edits` to it). + * + * Note that `applyEdits` not invoked when `onDidEdit` is fired by your extension because `onDidEdit` implies + * that your extension has also updated its editor instances (webviews) to reflect the edit that just occurred. + * + * @param document Document to apply edits to. + * @param redoneEdits Array of edits that were redone. Sorted from oldest to most recent. Use [`document.appliedEdits`](#CustomDocument.appliedEdits) + * to get the full set of edits applied to the file (when `applyEdits` is called `appliedEdits` will already include + * the newly applied edit at the end). + * + * @return Thenable signaling that the change has completed. + */ + applyEdits(document: CustomDocument, redoneEdits: ReadonlyArray): Thenable; + + /** + * Undo a list of edits to a custom editor. + * + * This method is invoked by VS Code when the user triggers `undo` in a custom editor. + * + * To implement `undoEdits`, the delegate must make sure all editor instances (webviews) for `document` + * are updated to render the document's new state (that is, every webview must be updated to show the document + * after undoing `edits` from it). + * + * @param document Document to undo edits from. + * @param undoneEdits Array of undone edits. Sorted from most recent to oldest. Use [`document.appliedEdits`](#CustomDocument.appliedEdits) + * to get the full set of edits applied to the file (when `undoEdits` is called, `appliedEdits` will already include + * have the undone edits removed). + * + * @return Thenable signaling that the change has completed. + */ + undoEdits(document: CustomDocument, undoneEdits: ReadonlyArray): Thenable; + + /** + * Revert a custom editor to its last saved state. + * + * This method is invoked by VS Code when the user triggers `File: Revert File` in a custom editor. (Note that + * this is only used using VS Code's `File: Revert File` command and not on a `git revert` of the file). + * + * To implement `revert`, the delegate must make sure all editor instances (webviews) for `document` + * are displaying the document in the same state is saved in. This usually means reloading the file from the + * workspace. + * + * During `revert`, your extension should also clear any backups for the custom editor. Backups are only needed + * when there is a difference between an editor's state in VS Code and its save state on disk. + * + * @param document Document to revert. + * @param revert Object with added or removed edits to get back to the saved state. Use [`document.appliedEdits`](#CustomDocument.appliedEdits) + * to get the full set of edits applied to the file (when `revet` is called, `appliedEdits` will already have + * removed any edits undone by the revert and added any edits applied by the revert). + * + * @return Thenable signaling that the change has completed. + */ + revert(document: CustomDocument, revert: CustomDocumentRevert): Thenable; + + /** + * Back up the resource in its current state. + * + * Backups are used for hot exit and to prevent data loss. Your `backup` method should persist the resource in + * its current state, i.e. with the edits applied. Most commonly this means saving the resource to disk in + * the `ExtensionContext.storagePath`. When VS Code reloads and your custom editor is opened for a resource, + * your extension should first check to see if any backups exist for the resource. If there is a backup, your + * extension should load the file contents from there instead of from the resource in the workspace. + * + * `backup` is triggered whenever an edit it made. Calls to `backup` are debounced so that if multiple edits are + * made in quick succession, `backup` is only triggered after the last one. `backup` is not invoked when + * `auto save` is enabled (since auto save already persists resource ). + * + * @param document Document to backup. + * @param cancellation Token that signals the current backup since a new backup is coming in. It is up to your + * extension to decided how to respond to cancellation. If for example your extension is backing up a large file + * in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather + * than cancelling it to ensure that VS Code has some valid backup. + */ + backup(document: CustomDocument, cancellation: CancellationToken): Thenable; + } + + /** + * Event triggered by extensions to signal to VS Code that an edit has occurred on a `CustomDocument`. + * + * @param EditType Type of edits used for the document. + */ + interface CustomDocumentEditEvent { + /** + * Document the edit is for. + */ + readonly document: CustomDocument; + + /** + * Object that describes the edit. + * + * Edit objects are controlled entirely by your extension. Your extension should store whatever information it + * needs to on the edit to understand what type of edit was made, how to render that edit, and how to save that + * edit to disk. + * + * Edit objects are passed back to your extension in `CustomEditorEditingDelegate.undoEdits`, + * `CustomEditorEditingDelegate.applyEdits`, and `CustomEditorEditingDelegate.revert`. They can also be accessed + * using [`CustomDocument.appliedEdits`](#CustomDocument.appliedEdits) and [`CustomDocument.savedEdits`](#CustomDocument.savedEdits). + */ + readonly edit: EditType; + + /** + * Display name describing the edit. + */ + readonly label?: string; + } + + /** + * Delta for edits undone/redone while reverting for a `CustomDocument`. + * + * @param EditType Type of edits used for the document being reverted. + */ + interface CustomDocumentRevert { + /** + * List of edits that were undone to get the document back to its on disk state. + */ + readonly undoneEdits: ReadonlyArray; + + /** + * List of edits that were reapplied to get the document back to its on disk state. + */ + readonly appliedEdits: ReadonlyArray; + } + + /** + * Represents a custom document used by a [`CustomEditorProvider`](#CustomEditorProvider). + * + * Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a `CustomDocument` is + * managed by VS Code. When no more references remain to a `CustomDocument`, it is disposed of. + * + * @param EditType Type of edits used in this document. + */ + class CustomDocument { + /** + * @param uri The associated resource for this document. + */ + constructor(uri: Uri); + + /** + * The associated uri for this document. + */ + readonly uri: Uri; + + /** + * Is this document representing an untitled file which has never been saved yet. + */ + readonly isUntitled: boolean; + + /** + * The version number of this document (it will strictly increase after each + * change, including undo/redo). + */ + readonly version: number; + + /** + * `true` if there are unpersisted changes. + */ + readonly isDirty: boolean; + + /** + * List of edits from document open to the document's current state. + * + * `appliedEdits` returns a copy of the edit stack at the current point in time. Your extension should always + * use `CustomDocument.appliedEdits` to check the edit stack instead of holding onto a reference to `appliedEdits`. + */ + readonly appliedEdits: ReadonlyArray; + + /** + * List of edits from document open to the document's last saved point. + * + * The save point will be behind `appliedEdits` if the user saves and then continues editing, + * or in front of the last entry in `appliedEdits` if the user saves and then hits undo. + * + * `savedEdits` returns a copy of the edit stack at the current point in time. Your extension should always + * use `CustomDocument.savedEdits` to check the edit stack instead of holding onto a reference to `savedEdits`. + */ + readonly savedEdits: ReadonlyArray; + + /** + * `true` if the document has been closed. A closed document isn't synchronized anymore + * and won't be reused when the same resource is opened again. + */ + readonly isClosed: boolean; + + /** + * Event fired when there are no more references to the `CustomDocument`. + * + * This happens when all custom editors for the document have been closed. Once a `CustomDocument` is disposed, + * it will not be reused when the same resource is opened again. + */ + readonly onDidDispose: Event; + } + + /** + * Provider for custom editors that use a custom document model. + * + * Custom editors use [`CustomDocument`](#CustomDocument) as their document model instead of a [`TextDocument`](#TextDocument). + * This gives extensions full control over actions such as edit, save, and backup. + * + * You should use this type of custom editor when dealing with binary files or more complex scenarios. For simple + * text based documents, use [`CustomTextEditorProvider`](#CustomTextEditorProvider) instead. + * + * @param EditType Type of edits used by the editors of this provider. + */ + export interface CustomEditorProvider { + + /** + * Create a new document for a given resource. + * + * `openCustomDocument` is called when the first editor for a given resource is opened, and the resolve document + * is passed to `resolveCustomEditor`. The resolved `CustomDocument` is re-used for subsequent editor opens. + * If all editors for a given resource are closed, the `CustomDocument` is disposed of. Opening an editor at + * this point will trigger another call to `openCustomDocument`. + * + * @param uri Uri of the document to open. + * @param token A cancellation token that indicates the result is no longer needed. + * + * @return The custom document. + */ + openCustomDocument(uri: Uri, token: CancellationToken): Thenable> | CustomDocument; + + /** + * Resolve a custom editor for a given resource. + * + * This is called whenever the user opens a new editor for this `CustomEditorProvider`. + * + * To resolve a custom editor, the provider must fill in its initial html content and hook up all + * the event listeners it is interested it. The provider can also hold onto the `WebviewPanel` to use later, + * for example in a command. See [`WebviewPanel`](#WebviewPanel) for additional details. + * + * @param document Document for the resource being resolved. + * @param webviewPanel Webview to resolve. + * @param token A cancellation token that indicates the result is no longer needed. + * + * @return Optional thenable indicating that the custom editor has been resolved. + */ + resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable | void; + + /** + * Defines the editing capability of the provider. + * + * When not provided, editors for this provider are considered readonly. + */ + readonly editingDelegate?: CustomEditorEditingDelegate; + } + + namespace window { + /** + * Temporary overload for `registerCustomEditorProvider` that takes a `CustomEditorProvider`. + */ + export function registerCustomEditorProvider2( + viewType: string, + provider: CustomEditorProvider, + options?: { + readonly webviewOptions?: WebviewPanelOptions; + } + ): Disposable; + } + + // #endregion + //#region Custom editor move https://github.com/microsoft/vscode/issues/86146 // TODO: Also for custom editor @@ -1352,7 +1676,7 @@ declare module 'vscode' { } export interface NotebookEditorCellEdit { - insert(index: number, content: string, language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; + insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; delete(index: number): void; } diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index f1864ca179..71d5cd0816 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -35,6 +35,7 @@ const BUILT_IN_AUTH_DEPENDENTS: AuthDependent[] = [ interface AllowedExtension { id: string; name: string; + sessionIds?: string[]; } function readAllowedExtensions(storageService: IStorageService, providerId: string, accountName: string): AllowedExtension[] { @@ -85,6 +86,16 @@ export class MainThreadAuthenticationProvider extends Disposable { quickPick.onDidAccept(() => { const updatedAllowedList = quickPick.selectedItems.map(item => item.extension); storageService.store(`${this.id}-${accountName}`, JSON.stringify(updatedAllowedList), StorageScope.GLOBAL); + + // Remove sessions of untrusted extensions + const deselectedItems = items.filter(item => !quickPick.selectedItems.includes(item)); + deselectedItems.forEach(item => { + const extensionData = allowedExtensions.find(extension => item.extension.id === extension.id); + extensionData?.sessionIds?.forEach(sessionId => { + this.logout(sessionId); + }); + }); + quickPick.dispose(); }); @@ -275,9 +286,19 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu this.authenticationService.sessionsUpdate(id, event); } - async $getSessionsPrompt(providerId: string, accountName: string, providerName: string, extensionId: string, extensionName: string): Promise { - let allowList = readAllowedExtensions(this.storageService, providerId, accountName); - if (allowList.some(extension => extension.id === extensionId)) { + async $getSessionsPrompt(providerId: string, accountName: string, sessionId: string, providerName: string, extensionId: string, extensionName: string): Promise { + const allowList = readAllowedExtensions(this.storageService, providerId, accountName); + const extensionData = allowList.find(extension => extension.id === extensionId); + if (extensionData) { + if (!extensionData.sessionIds) { + extensionData.sessionIds = []; + } + + if (!extensionData.sessionIds.find(id => id === sessionId)) { + extensionData.sessionIds.push(sessionId); + this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + } + return true; } @@ -292,7 +313,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu const allow = choice === 1; if (allow) { - allowList = allowList.concat({ id: extensionId, name: extensionName }); + allowList.push({ id: extensionId, name: extensionName, sessionIds: [sessionId] }); this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); } @@ -313,7 +334,10 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu } async $setTrustedExtension(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise { - const allowList = readAllowedExtensions(this.storageService, providerId, accountName).concat({ id: extensionId, name: extensionName }); - this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + const allowList = readAllowedExtensions(this.storageService, providerId, accountName); + if (!allowList.find(allowed => allowed.id === extensionId)) { + allowList.push({ id: extensionId, name: extensionName, sessionIds: [] }); + this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + } } } diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index 53e92a221f..b2bb510cf6 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -267,7 +267,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma resolveWebview: async (webviewInput): Promise => { const viewType = webviewPanelViewType.toExternal(webviewInput.viewType); if (!viewType) { - webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(webviewInput.viewType); + webviewInput.webview.html = MainThreadWebviews.getWebviewResolvedFailedContent(webviewInput.viewType); return; } @@ -288,7 +288,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma await this._proxy.$deserializeWebviewPanel(handle, viewType, webviewInput.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), webviewInput.webview.options); } catch (error) { onUnexpectedError(error); - webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType); + webviewInput.webview.html = MainThreadWebviews.getWebviewResolvedFailedContent(viewType); } } })); @@ -339,7 +339,15 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma webviewInput.webview.options = options; webviewInput.webview.extension = extension; - let modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, cancellation); + let modelRef: IReference; + try { + modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, cancellation); + } catch (error) { + onUnexpectedError(error); + webviewInput.webview.html = MainThreadWebviews.getWebviewResolvedFailedContent(viewType); + return; + } + if (cancellation.isCancellationRequested) { modelRef.dispose(); return; @@ -362,7 +370,8 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma await this._proxy.$resolveWebviewEditor(resource, handle, viewType, webviewInput.getTitle(), editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), webviewInput.webview.options, cancellation); } catch (error) { onUnexpectedError(error); - webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType); + webviewInput.webview.html = MainThreadWebviews.getWebviewResolvedFailedContent(viewType); + modelRef.dispose(); return; } } @@ -522,14 +531,14 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma return this._webviewInputs.getInputForHandle(handle); } - private static getDeserializationFailedContents(viewType: string) { + private static getWebviewResolvedFailedContent(viewType: string) { return ` - ${localize('errorMessage', "An error occurred while restoring view:{0}", escape(viewType))} + ${localize('errorMessage', "An error occurred while loading view: {0}", escape(viewType))} `; } } @@ -795,6 +804,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod return undefined; } // TODO: handle save untitled case + // TODO: handle cancellation await createCancelablePromise(token => this._proxy.$onSave(this._editorResource, this.viewType, token)); this.change(() => { this._savePoint = this._currentEditIndex; @@ -804,7 +814,8 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod public async saveCustomEditorAs(resource: URI, targetResource: URI, _options?: ISaveOptions): Promise { if (this._editable) { - await this._proxy.$onSaveAs(this._editorResource, this.viewType, targetResource); + // TODO: handle cancellation + await createCancelablePromise(token => this._proxy.$onSaveAs(this._editorResource, this.viewType, targetResource, token)); this.change(() => { this._savePoint = this._currentEditIndex; }); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 9af9e0b638..da05065c4e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -134,7 +134,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol)); const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors)); const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol)); - const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol)); + const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol, extHostStorage)); const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands)); const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment, extHostWorkspace, extHostLogService, extHostApiDeprecation, extHostDocuments)); @@ -585,7 +585,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => { return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer); }, - registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => { + registerCustomEditorProvider: (viewType: string, provider: vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => { + return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions); + }, + registerCustomEditorProvider2: (viewType: string, provider: vscode.CustomEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => { + checkProposedApiEnabled(extension); return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions); }, registerDecorationProvider(provider: vscode.DecorationProvider) { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index dd5d4c5d55..5e397c3acb 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -162,7 +162,7 @@ export interface MainThreadAuthenticationShape extends IDisposable { $registerAuthenticationProvider(id: string, displayName: string): void; $unregisterAuthenticationProvider(id: string): void; $onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void; - $getSessionsPrompt(providerId: string, accountName: string, providerName: string, extensionId: string, extensionName: string): Promise; + $getSessionsPrompt(providerId: string, accountName: string, sessionId: string, providerName: string, extensionId: string, extensionName: string): Promise; $loginPrompt(providerName: string, extensionName: string): Promise; $setTrustedExtension(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise; } @@ -653,7 +653,7 @@ export interface ExtHostWebviewsShape { $disposeEdits(resourceComponents: UriComponents, viewType: string, editIds: number[]): void; $onSave(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; - $onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise; + $onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents, cancellation: CancellationToken): Promise; $backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 338eed5ea2..620303ff99 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -9,6 +9,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IMainContext, MainContext, MainThreadAuthenticationShape, ExtHostAuthenticationShape } from 'vs/workbench/api/common/extHost.protocol'; import { Disposable } from 'vs/workbench/api/common/extHostTypes'; import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { IExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; export class ExtHostAuthentication implements ExtHostAuthenticationShape { private _proxy: MainThreadAuthenticationShape; @@ -20,7 +21,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { private _onDidChangeSessions = new Emitter<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }>(); readonly onDidChangeSessions: Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> = this._onDidChangeSessions.event; - constructor(mainContext: IMainContext) { + constructor(mainContext: IMainContext, + @IExtHostStorage private readonly storageService: IExtHostStorage) { this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication); } @@ -33,15 +35,34 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { return ids; } + private async hasNotBeenReadByOtherExtension(providerId: string, session: vscode.AuthenticationSession, extensionId: string): Promise { + const readerId = await this.storageService.getValue(true, `${providerId}-${session.accountName}-${session.id}`); + if (!readerId) { + await this.storageService.setValue(true, `${providerId}-${session.accountName}-${session.id}`, extensionId as any); + return true; + } + + return readerId === extensionId; + } + + private async isMatchingSession(session: vscode.AuthenticationSession, scopes: string, providerId: string, extensionId: string): Promise { + return session.scopes.sort().join(' ') === scopes && (await this.hasNotBeenReadByOtherExtension(providerId, session, extensionId)); + } + async getSessions(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise { const provider = this._authenticationProviders.get(providerId); if (!provider) { throw new Error(`No authentication provider with id '${providerId}' is currently registered.`); } + const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); const orderedScopes = scopes.sort().join(' '); - return (await provider.getSessions()) - .filter(session => session.scopes.sort().join(' ') === orderedScopes) + + const sessions = await provider.getSessions(); + const filteredSessions = await Promise.all(sessions.map(session => this.isMatchingSession(session, orderedScopes, providerId, extensionId))); + + return sessions + .filter((_, i) => { return filteredSessions[i]; }) .map(session => { return { id: session.id, @@ -51,8 +72,9 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { const isAllowed = await this._proxy.$getSessionsPrompt( provider.id, session.accountName, + session.id, provider.displayName, - ExtensionIdentifier.toKey(requestingExtension.identifier), + extensionId, requestingExtension.displayName || requestingExtension.name); if (!isAllowed) { @@ -77,9 +99,28 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { throw new Error('User did not consent to login.'); } - const newSession = await provider.login(scopes); - await this._proxy.$setTrustedExtension(provider.id, newSession.accountName, ExtensionIdentifier.toKey(requestingExtension.identifier), extensionName); - return newSession; + const session = await provider.login(scopes); + await this._proxy.$setTrustedExtension(provider.id, session.accountName, ExtensionIdentifier.toKey(requestingExtension.identifier), extensionName); + return { + id: session.id, + accountName: session.accountName, + scopes: session.scopes, + getAccessToken: async () => { + const isAllowed = await this._proxy.$getSessionsPrompt( + provider.id, + session.accountName, + session.id, + provider.displayName, + ExtensionIdentifier.toKey(requestingExtension.identifier), + requestingExtension.displayName || requestingExtension.name); + + if (!isAllowed) { + throw new Error('User did not consent to token access.'); + } + + return session.getAccessToken(); + } + }; } registerAuthenticationProvider(provider: vscode.AuthenticationProvider): vscode.Disposable { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index c28497751b..3c4cb8b11d 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -402,11 +402,12 @@ export class NotebookEditorCellEdit { } } - insert(index: number, content: string, language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): void { + insert(index: number, content: string | string[], language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): void { this._throwIfFinalized(); + const sourceArr = Array.isArray(content) ? content : content.split(/\r|\n|\r\n/g); let cell = { - source: [content], + source: sourceArr, language, cellKind: type, outputs: (outputs as any[]), // TODO@rebornix diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 871977039b..8b72aa93a6 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -16,7 +16,7 @@ import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/p import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver'; import type * as vscode from 'vscode'; import { Cache } from './cache'; -import { assertIsDefined } from 'vs/base/common/types'; +import { assertIsDefined, isStringArray } from 'vs/base/common/types'; import { Schemas } from 'vs/base/common/network'; function es5ClassCompat(target: Function): any { @@ -2420,25 +2420,14 @@ export class SemanticTokensLegend { public readonly tokenTypes: string[]; public readonly tokenModifiers: string[]; - constructor(tokenTypes: string[], tokenModifiers: string[]) { + constructor(tokenTypes: string[], tokenModifiers: string[] = []) { this.tokenTypes = tokenTypes; this.tokenModifiers = tokenModifiers; } } function isStrArrayOrUndefined(arg: any): arg is string[] | undefined { - if (typeof arg === 'undefined') { - return true; - } - if (Array.isArray(arg)) { - for (const element of arg) { - if (typeof element !== 'string') { - return false; - } - } - return true; - } - return false; + return ((typeof arg === 'undefined') || isStringArray(arg)); } export class SemanticTokensBuilder { @@ -2472,10 +2461,13 @@ export class SemanticTokensBuilder { } } - public push(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void; + public push(line: number, char: number, length: number, tokenType: number, tokenModifiers?: number): void; public push(range: Range, tokenType: string, tokenModifiers?: string[]): void; public push(arg0: any, arg1: any, arg2: any, arg3?: any, arg4?: any): void { - if (typeof arg0 === 'number' && typeof arg1 === 'number' && typeof arg2 === 'number' && typeof arg3 === 'number' && typeof arg4 === 'number') { + if (typeof arg0 === 'number' && typeof arg1 === 'number' && typeof arg2 === 'number' && typeof arg3 === 'number' && (typeof arg4 === 'number' || typeof arg4 === 'undefined')) { + if (typeof arg4 === 'undefined') { + arg4 = 0; + } // 1st overload return this._pushEncoded(arg0, arg1, arg2, arg3, arg4); } diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index c73c721ce6..975ec95b76 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -630,10 +630,10 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape { return delegate.save(document, cancellation); } - async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise { + async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents, cancellation: CancellationToken): Promise { const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return delegate.saveAs(document, URI.revive(targetResource)); + return delegate.saveAs(document, URI.revive(targetResource), cancellation); } async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise { diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index c3ac5630c1..0517ba42d3 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -41,10 +41,10 @@ namespace schema { case 'menuBar/webNavigation': return MenuId.MenubarWebNavigationMenu; case 'scm/title': return MenuId.SCMTitle; case 'scm/sourceControl': return MenuId.SCMSourceControl; - case 'scm/resourceState/context': return MenuId.SCMResourceContext; + case 'scm/resourceState/context': return MenuId.SCMResourceContext;// case 'scm/resourceFolder/context': return MenuId.SCMResourceFolderContext; case 'scm/resourceGroup/context': return MenuId.SCMResourceGroupContext; - case 'scm/change/title': return MenuId.SCMChangeContext; + case 'scm/change/title': return MenuId.SCMChangeContext;// case 'statusBar/windowIndicator': return MenuId.StatusBarWindowIndicatorMenu; case 'view/title': return MenuId.ViewTitle; case 'view/item/context': return MenuId.ViewItemContext; @@ -171,6 +171,11 @@ namespace schema { type: 'array', items: menuItem }, + 'menuBar/webNavigation': { + description: localize('menus.webNavigation', "The top level navigational menu (web only)"), + type: 'array', + items: menuItem + }, 'scm/title': { description: localize('menus.scmTitle', "The Source Control title menu"), type: 'array', @@ -191,6 +196,16 @@ namespace schema { type: 'array', items: menuItem }, + 'scm/resourceFolder/context': { + description: localize('menus.resourceFolderContext', "The Source Control resource folder context menu"), + type: 'array', + items: menuItem + }, + 'scm/change/title': { + description: localize('menus.changeTitle', "The Source Control inline change menu"), + type: 'array', + items: menuItem + }, 'view/title': { description: localize('view.viewTitle', "The contributed view title menu"), type: 'array', diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index dba680c227..87e6a8f4f8 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -504,6 +504,37 @@ export class ResetViewLocationsAction extends Action { registry.registerWorkbenchAction(SyncActionDescriptor.create(ResetViewLocationsAction, ResetViewLocationsAction.ID, ResetViewLocationsAction.LABEL), 'View: Reset View Locations', viewCategory); +// --- Toggle View with Command +export abstract class ToggleViewAction extends Action { + + constructor( + id: string, + label: string, + private readonly viewId: string, + protected viewsService: IViewsService, + protected viewDescriptorService: IViewDescriptorService, + protected contextKeyService: IContextKeyService, + private layoutService: IWorkbenchLayoutService, + cssClass?: string + ) { + super(id, label, cssClass); + } + + async run(): Promise { + const focusedViewId = FocusedViewContext.getValue(this.contextKeyService); + + if (focusedViewId === this.viewId) { + if (this.viewDescriptorService.getViewLocation(this.viewId) === ViewContainerLocation.Sidebar) { + this.layoutService.setSideBarHidden(true); + } else { + this.layoutService.setPanelHidden(true); + } + } else { + this.viewsService.openView(this.viewId, true); + } + } +} + // --- Move View with Command export class MoveFocusedViewAction extends Action { static readonly ID = 'workbench.action.moveFocusedView'; @@ -541,6 +572,7 @@ export class MoveFocusedViewAction extends Action { const quickPick = this.quickInputService.createQuickPick(); quickPick.placeholder = nls.localize('moveFocusedView.selectDestination', "Select a Destination for the View"); + quickPick.title = nls.localize('moveFocusedView.title', "View: Move {0}", viewDescriptor.name); const items: Array = []; @@ -549,10 +581,16 @@ export class MoveFocusedViewAction extends Action { label: nls.localize('sidebar', "Side Bar") }); - items.push({ - id: '_.sidebar.newcontainer', - label: nls.localize('moveFocusedView.newContainerInSidebar', "New Container in Side Bar") - }); + const currentContainer = this.viewDescriptorService.getViewContainer(focusedViewId)!; + const currentLocation = this.viewDescriptorService.getViewLocation(focusedViewId)!; + const isViewSolo = this.viewDescriptorService.getViewDescriptors(currentContainer).allViewDescriptors.length === 1; + + if (!(isViewSolo && currentLocation === ViewContainerLocation.Sidebar)) { + items.push({ + id: '_.sidebar.newcontainer', + label: nls.localize('moveFocusedView.newContainerInSidebar', "New Container in Side Bar") + }); + } const pinnedViewlets = this.activityBarService.getPinnedViewletIds(); items.push(...pinnedViewlets @@ -574,10 +612,13 @@ export class MoveFocusedViewAction extends Action { type: 'separator', label: nls.localize('panel', "Panel") }); - items.push({ - id: '_.panel.newcontainer', - label: nls.localize('moveFocusedView.newContainerInPanel', "New Container in Panel"), - }); + + if (!(isViewSolo && currentLocation === ViewContainerLocation.Panel)) { + items.push({ + id: '_.panel.newcontainer', + label: nls.localize('moveFocusedView.newContainerInPanel', "New Container in Panel"), + }); + } const pinnedPanels = this.panelService.getPinnedPanels(); items.push(...pinnedPanels diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index b71a2c9b42..898988d31e 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -127,7 +127,7 @@ abstract class BaseOpenRecentAction extends Action { const pick = await this.quickInputService.pick(picks, { contextKey: inRecentFilesPickerContextKey, activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0], - placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"), + placeHolder: isMacintosh ? nls.localize('openRecentPlaceholderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceholder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"), matchOnDescription: true, onKeyMods: mods => keyMods = mods, quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined, @@ -196,6 +196,7 @@ abstract class BaseOpenRecentAction extends Action { return { iconClasses, label: name, + ariaLabel: isDirty ? nls.localize('recentDirtyAriaLabel', "{0}, dirty workspace", name) : name, description: parentPath, buttons: isDirty ? [this.dirtyRecentlyOpened] : [this.removeFromRecentlyOpened], openable, diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 41bc74f597..f02007c092 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -509,8 +509,10 @@ export function containsDragType(event: DragEvent, ...dragTypesToFind: string[]) return false; } +export type Before2D = { verticallyBefore: boolean; horizontallyBefore: boolean; }; + export interface ICompositeDragAndDrop { - drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: boolean): void; + drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: Before2D): void; onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean; onDragEnter(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean; } diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index 4d2f4f2f4d..e27dde8649 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -6,11 +6,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IPanel } from 'vs/workbench/common/panel'; import { Composite, CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite'; -import { Action } from 'vs/base/common/actions'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IConstructorSignature0, BrandedService } from 'vs/platform/instantiation/common/instantiation'; -import { isAncestor } from 'vs/base/browser/dom'; import { assertIsDefined } from 'vs/base/common/types'; import { PaneComposite } from 'vs/workbench/browser/panecomposite'; @@ -85,44 +81,6 @@ export class PanelRegistry extends CompositeRegistry { } } -/** - * A reusable action to toggle a panel with a specific id depending on focus. - */ -export abstract class TogglePanelAction extends Action { - - constructor( - id: string, - label: string, - private readonly panelId: string, - protected panelService: IPanelService, - private layoutService: IWorkbenchLayoutService, - cssClass?: string - ) { - super(id, label, cssClass); - } - - async run(): Promise { - if (this.isPanelFocused()) { - this.layoutService.setPanelHidden(true); - } else { - await this.panelService.openPanel(this.panelId, true); - } - } - - private isPanelActive(): boolean { - const activePanel = this.panelService.getActivePanel(); - - return activePanel?.getId() === this.panelId; - } - - private isPanelFocused(): boolean { - const activeElement = document.activeElement; - const panelPart = this.layoutService.getContainer(Parts.PANEL_PART); - - return !!(this.isPanelActive() && activeElement && panelPart && isAncestor(activeElement, panelPart)); - } -} - export const Extensions = { Panels: 'workbench.contributions.panels' }; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 52113c69cb..fea6887606 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -42,6 +42,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync'; import { IProductService } from 'vs/platform/product/common/productService'; +import { Before2D } from 'vs/workbench/browser/dnd'; interface IPlaceholderViewlet { id: string; @@ -152,7 +153,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { hidePart: () => this.layoutService.setSideBarHidden(true), dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar, (id: string, focus?: boolean) => this.viewletService.openViewlet(id, focus), - (from: string, to: string, before?: boolean) => this.compositeBar.move(from, to, before) + (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore) ), compositeSize: 50, colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme), diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index e901ea537d..7e4e233fe5 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -23,7 +23,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IComposite } from 'vs/workbench/common/composite'; -import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd'; +import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd'; export interface ICompositeBarItem { id: string; @@ -39,9 +39,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { private viewDescriptorService: IViewDescriptorService, private targetContainerLocation: ViewContainerLocation, private openComposite: (id: string, focus?: boolean) => Promise, - private moveComposite: (from: string, to: string, before?: boolean) => void, + private moveComposite: (from: string, to: string, before?: Before2D) => void, ) { } - drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: boolean): void { + drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: Before2D): void { const dragData = data.getData(); const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); @@ -255,7 +255,7 @@ export class CompositeBar extends Widget implements ICompositeBar { }, onDrop: (e: IDraggedCompositeData) => { const pinnedItems = this.getPinnedComposites(); - this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, false); + this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, { horizontallyBefore: false, verticallyBefore: false }); toggleClass(parent, 'dragged-over', false); } })); diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 4b5b7f9389..d2bc6f741c 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -18,7 +18,7 @@ import { DelayedDragHandler } from 'vs/base/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Emitter } from 'vs/base/common/event'; -import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd'; +import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd'; import { Color } from 'vs/base/common/color'; export interface ICompositeActivity { @@ -516,7 +516,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { this.showContextMenu(container); })); - let insertDropBefore: boolean | undefined = undefined; + let insertDropBefore: Before2D | undefined = undefined; // Allow to drag this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, () => { return { type: 'composite', id: this.activity.id }; }, { onDragOver: e => { @@ -534,7 +534,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { onDrop: e => { dom.EventHelper.stop(e.eventData, true); - this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, !!insertDropBefore); + this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, insertDropBefore); insertDropBefore = this.updateFromDragging(container, false, e.eventData); }, onDragStart: e => { @@ -563,7 +563,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { this.updateStyles(); } - private updateFromDragging(element: HTMLElement, showFeedback: boolean, event: DragEvent): boolean | undefined { + private updateFromDragging(element: HTMLElement, showFeedback: boolean, event: DragEvent): Before2D | undefined { const rect = element.getBoundingClientRect(); const posX = event.clientX; const posY = event.clientY; @@ -598,7 +598,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { return undefined; } - return top || left; + return { verticallyBefore: top, horizontallyBefore: left }; } private showContextMenu(container: HTMLElement): void { diff --git a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts index 087bc38d31..170004719e 100644 --- a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts +++ b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts @@ -8,22 +8,24 @@ import { localize } from 'vs/nls'; import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource, IQuickPick } from 'vs/platform/quickinput/common/quickInput'; import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IEditorGroupsService, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor, GroupIdentifier } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; -import { prepareQuery, scoreItem, compareItemsByScore, ScorerCache } from 'vs/base/common/fuzzyScorer'; +import { prepareQuery, scoreItemFuzzy, compareItemsByFuzzyScore, FuzzyScorerCache } from 'vs/base/common/fuzzyScorer'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IDisposable } from 'vs/base/common/lifecycle'; -interface IEditorQuickPickItem extends IQuickPickItemWithResource, IEditorIdentifier, IPickerQuickAccessItem { } +interface IEditorQuickPickItem extends IQuickPickItemWithResource, IPickerQuickAccessItem { + groupId: GroupIdentifier; +} export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessProvider { private readonly pickState = new class { - scorerCache: ScorerCache = Object.create(null); + scorerCache: FuzzyScorerCache = Object.create(null); isQuickNavigating: boolean | undefined = undefined; reset(isQuickNavigating: boolean): void { @@ -45,7 +47,15 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro @IModelService private readonly modelService: IModelService, @IModeService private readonly modeService: IModeService ) { - super(prefix, { canAcceptInBackground: true }); + super(prefix, + { + canAcceptInBackground: true, + noResultsPick: { + label: localize('noViewResults', "No matching editors"), + groupId: -1 + } + } + ); } provide(picker: IQuickPick, token: CancellationToken): IDisposable { @@ -67,7 +77,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro } // Score on label and description - const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); + const itemScore = scoreItemFuzzy(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); if (!itemScore.score) { return false; } @@ -86,7 +96,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro return groups.indexOf(entryA.groupId) - groups.indexOf(entryB.groupId); // older groups first } - return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); + return compareItemsByFuzzyScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); }); } @@ -113,16 +123,35 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro } private doGetEditorPickItems(): Array { + const editors = this.doGetEditors(); + + const mapGroupIdToGroupAriaLabel = new Map(); + for (const { groupId } of editors) { + if (!mapGroupIdToGroupAriaLabel.has(groupId)) { + const group = this.editorGroupService.getGroup(groupId); + if (group) { + mapGroupIdToGroupAriaLabel.set(groupId, group.ariaLabel); + } + } + } + return this.doGetEditors().map(({ editor, groupId }): IEditorQuickPickItem => { const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER }); const isDirty = editor.isDirty() && !editor.isSaving(); return { - editor, groupId, resource, label: editor.getName(), - ariaLabel: localize('entryAriaLabel', "{0}, editors picker", editor.getName()), + ariaLabel: (() => { + if (mapGroupIdToGroupAriaLabel.size > 1) { + return isDirty ? + localize('entryAriaLabelWithGroupDirty', "{0}, dirty, {1}", editor.getName(), mapGroupIdToGroupAriaLabel.get(groupId)) : + localize('entryAriaLabelWithGroup', "{0}, {1}", editor.getName(), mapGroupIdToGroupAriaLabel.get(groupId)); + } + + return isDirty ? localize('entryAriaLabelDirty', "{0}, dirty", editor.getName()) : editor.getName(); + })(), description: editor.getDescription(), iconClasses: getIconClasses(this.modelService, this.modeService, resource), italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor), diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 5fd07baa98..f735ecac8f 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -38,6 +38,7 @@ import { MenuId } from 'vs/platform/actions/common/actions'; import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { Before2D } from 'vs/workbench/browser/dnd'; interface ICachedPanel { id: string; @@ -147,8 +148,8 @@ export class PanelPart extends CompositePart implements IPanelService { getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(), hidePart: () => this.layoutService.setPanelHidden(true), dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel, - (id: string, focus?: boolean) => this.openPanel(id, focus) as Promise, // {{SQL CARBON EDIT}} strict-null-checks - (from: string, to: string, before?: boolean) => this.compositeBar.move(from, to, before) + (id: string, focus?: boolean) => this.openPanel(id, focus) as Promise, // {{SQL CARBON EDIT}} strict-null-checks + (from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore) ), compositeSize: 0, overflowActionSize: 44, diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 93c51077aa..c108610a31 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -428,7 +428,7 @@ export class CustomMenubarControl extends MenubarControl { return new Action('update.checking', nls.localize('checkingForUpdates', "Checking for Updates..."), undefined, false); case StateType.AvailableForDownload: - return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Now"), undefined, true, () => + return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Update"), undefined, true, () => this.updateService.downloadUpdate()); case StateType.Downloading: diff --git a/src/vs/workbench/browser/parts/views/media/paneviewlet.css b/src/vs/workbench/browser/parts/views/media/paneviewlet.css index 43160a1992..b740c4cdc6 100644 --- a/src/vs/workbench/browser/parts/views/media/paneviewlet.css +++ b/src/vs/workbench/browser/parts/views/media/paneviewlet.css @@ -6,6 +6,9 @@ .monaco-pane-view .split-view-view:first-of-type > .pane > .pane-header { border-top: none !important; /* less clutter: do not show any border for first views in a pane */ } +.monaco-pane-view .split-view-view:first-of-type > .pane { + border-left: none !important; /* less clutter: do not show any border for first views in a pane */ +} .monaco-pane-view .pane > .pane-header { position: relative; @@ -24,10 +27,6 @@ -webkit-margin-after: 0; } -.monaco-pane-view .pane > .pane-header h3.title:first-child { - margin-left: 7px; -} - .monaco-pane-view .pane .monaco-progress-container { position: absolute; left: 0; diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index 6c63627666..a8dca1c5f8 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -52,9 +52,9 @@ .monaco-workbench .pane > .pane-body > .welcome-view { width: 100%; height: 100%; - padding: 0 20px 0 20px; - position: absolute; box-sizing: border-box; + display: flex; + flex-direction: column; } .monaco-workbench .pane > .pane-body:not(.welcome) > .welcome-view, @@ -69,6 +69,15 @@ display: block; } +.monaco-workbench .pane > .pane-body .welcome-view-content { + padding: 0 20px 0 20px; + box-sizing: border-box; +} + +.monaco-workbench .pane > .pane-body .welcome-view-content > *:last-child { + margin-bottom: 1em; +} + .customview-tree .monaco-list-row .monaco-tl-contents.align-icon-with-twisty::before { display: none; } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 14d27c5fc9..7ef7062a71 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { ColorIdentifier, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler'; -import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, EDITOR_DRAG_AND_DROP_BACKGROUND, PANEL_BORDER } from 'vs/workbench/common/theme'; import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass } from 'vs/base/browser/dom'; import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { firstIndex } from 'vs/base/common/arrays'; @@ -47,12 +47,15 @@ import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { CompositeProgressIndicator } from 'vs/workbench/services/progress/browser/progressIndicator'; import { IProgressIndicator } from 'vs/platform/progress/common/progress'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/common/scrollable'; export interface IPaneColors extends IColorMapping { dropBackground?: ColorIdentifier; headerForeground?: ColorIdentifier; headerBackground?: ColorIdentifier; headerBorder?: ColorIdentifier; + leftBorder?: ColorIdentifier; } export interface IViewPaneOptions extends IPaneOptions { @@ -309,9 +312,20 @@ export abstract class ViewPane extends Pane implements IView { this._onDidChangeTitleArea.fire(); } + private scrollableElement!: DomScrollableElement; + protected renderBody(container: HTMLElement): void { this.bodyContainer = container; - this.viewWelcomeContainer = append(container, $('.welcome-view', { tabIndex: 0 })); + + const viewWelcomeContainer = append(container, $('.welcome-view')); + this.viewWelcomeContainer = $('.welcome-view-content', { tabIndex: 0 }); + this.scrollableElement = this._register(new DomScrollableElement(this.viewWelcomeContainer, { + alwaysConsumeMouseWheel: true, + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Visible, + })); + + append(viewWelcomeContainer, this.scrollableElement.getDomNode()); const onViewWelcomeChange = Event.any(this.viewWelcomeController.onDidChange, this.onDidChangeViewWelcomeState); this._register(onViewWelcomeChange(this.updateViewWelcome, this)); @@ -319,7 +333,9 @@ export abstract class ViewPane extends Pane implements IView { } protected layoutBody(height: number, width: number): void { - // noop + this.viewWelcomeContainer.style.height = `${height}px`; + this.viewWelcomeContainer.style.width = `${width}px`; + this.scrollableElement.scanDomNode(); } getProgressIndicator() { @@ -410,6 +426,7 @@ export abstract class ViewPane extends Pane implements IView { if (!this.shouldShowWelcome()) { removeClass(this.bodyContainer, 'welcome'); this.viewWelcomeContainer.innerHTML = ''; + this.scrollableElement.scanDomNode(); return; } @@ -418,6 +435,7 @@ export abstract class ViewPane extends Pane implements IView { if (contents.length === 0) { removeClass(this.bodyContainer, 'welcome'); this.viewWelcomeContainer.innerHTML = ''; + this.scrollableElement.scanDomNode(); return; } @@ -437,47 +455,52 @@ export abstract class ViewPane extends Pane implements IView { continue; } - const p = append(this.viewWelcomeContainer, $('p')); const linkedText = parseLinkedText(line); - for (const node of linkedText.nodes) { - if (typeof node === 'string') { - append(p, document.createTextNode(node)); - } else if (linkedText.nodes.length === 1) { - const button = new Button(p, { title: node.title }); - button.label = node.label; - button.onDidClick(_ => { - this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href }); - this.openerService.open(node.href); - }, null, disposables); - disposables.add(button); - disposables.add(attachButtonStyler(button, this.themeService)); + if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') { + const node = linkedText.nodes[0]; + const button = new Button(this.viewWelcomeContainer, { title: node.title }); + button.label = node.label; + button.onDidClick(_ => { + this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href }); + this.openerService.open(node.href); + }, null, disposables); + disposables.add(button); + disposables.add(attachButtonStyler(button, this.themeService)); - if (preconditions) { - const precondition = preconditions[buttonIndex]; + if (preconditions) { + const precondition = preconditions[buttonIndex]; - if (precondition) { - const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); - updateEnablement(); + if (precondition) { + const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition); + updateEnablement(); - const keys = new Set(); - precondition.keys().forEach(key => keys.add(key)); - const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); - onDidChangeContext(updateEnablement, null, disposables); - } + const keys = new Set(); + precondition.keys().forEach(key => keys.add(key)); + const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys)); + onDidChangeContext(updateEnablement, null, disposables); } + } - buttonIndex++; - } else { - const link = this.instantiationService.createInstance(Link, node); - append(p, link.el); - disposables.add(link); - disposables.add(attachLinkStyler(link, this.themeService)); + buttonIndex++; + } else { + const p = append(this.viewWelcomeContainer, $('p')); + + for (const node of linkedText.nodes) { + if (typeof node === 'string') { + append(p, document.createTextNode(node)); + } else { + const link = this.instantiationService.createInstance(Link, node); + append(p, link.el); + disposables.add(link); + disposables.add(attachLinkStyler(link, this.themeService)); + } } } } } + this.scrollableElement.scanDomNode(); this.viewWelcomeDisposable = disposables; } @@ -523,7 +546,7 @@ class ViewPaneDropOverlay extends Themable { constructor( private paneElement: HTMLElement, - private orientation: Orientation, + private orientation: Orientation | undefined, protected themeService: IThemeService ) { super(themeService); @@ -540,6 +563,7 @@ class ViewPaneDropOverlay extends Themable { // Container this.container = document.createElement('div'); this.container.id = ViewPaneDropOverlay.OVERLAY_ID; + this.container.style.top = '0px'; // Parent this.paneElement.appendChild(this.container); @@ -575,6 +599,7 @@ class ViewPaneDropOverlay extends Themable { this.overlay.style.borderColor = activeContrastBorderColor || ''; this.overlay.style.borderStyle = 'solid' || ''; + this.overlay.style.borderWidth = '0px'; } private registerListeners(): void { @@ -629,7 +654,7 @@ class ViewPaneDropOverlay extends Themable { } else if (mousePosY >= splitHeightThreshold) { dropDirection = DropDirection.DOWN; } - } else { + } else if (this.orientation === Orientation.HORIZONTAL) { if (mousePosX < splitWidthThreshold) { dropDirection = DropDirection.LEFT; } else if (mousePosX >= splitWidthThreshold) { @@ -655,7 +680,12 @@ class ViewPaneDropOverlay extends Themable { this.doPositionOverlay({ top: '0', left: '0', width: '100%', height: '100%' }); } - this.doUpdateOverlayBorder(dropDirection); + if ((this.orientation === Orientation.VERTICAL && paneHeight <= 25) || + (this.orientation === Orientation.HORIZONTAL && paneWidth <= 25)) { + this.doUpdateOverlayBorder(dropDirection); + } else { + this.doUpdateOverlayBorder(undefined); + } // Make sure the overlay is visible now this.overlay.style.opacity = '1'; @@ -788,6 +818,71 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane))); this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e)))); + let overlay: ViewPaneDropOverlay | undefined; + this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, { + onDragEnter: (e) => { + if (!overlay && this.panes.length === 0) { + const dropData = e.dragAndDropData.getData(); + if (dropData.type === 'view') { + + const oldViewContainer = this.viewDescriptorService.getViewContainer(dropData.id); + const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dropData.id); + + if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView)) { + return; + } + + overlay = new ViewPaneDropOverlay(parent, undefined, this.themeService); + } + + if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) { + const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); + + const container = viewContainerRegistry.get(dropData.id)!; + const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors; + + if (viewsToMove.length === 1 && viewsToMove[0].canMoveView) { + overlay = new ViewPaneDropOverlay(parent, undefined, this.themeService); + } + } + + } + }, + onDragLeave: (e) => { + overlay?.dispose(); + overlay = undefined; + }, + onDrop: (e) => { + if (overlay) { + const dropData = e.dragAndDropData.getData(); + + if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) { + const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); + + const container = viewContainerRegistry.get(dropData.id)!; + const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors; + + if (viewsToMove.length === 1 && viewsToMove[0].canMoveView) { + dropData.type = 'view'; + dropData.id = viewsToMove[0].id; + } + } + + if (dropData.type === 'view') { + + const oldViewContainer = this.viewDescriptorService.getViewContainer(dropData.id); + const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dropData.id); + if (oldViewContainer !== this.viewContainer && viewDescriptor && viewDescriptor.canMoveView) { + this.viewDescriptorService.moveViewsToContainer([viewDescriptor], this.viewContainer); + } + } + } + + overlay?.dispose(); + overlay = undefined; + } + })); + this._register(this.onDidSashChange(() => this.saveViewSizes())); this.viewsModel.onDidAdd(added => this.onDidAddViewDescriptors(added)); this.viewsModel.onDidRemove(removed => this.onDidRemoveViewDescriptors(removed)); @@ -1143,6 +1238,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND, headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND, headerBorder: SIDE_BAR_SECTION_HEADER_BORDER, + leftBorder: PANEL_BORDER, dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND }, pane); const disposable = combinedDisposable(onDidFocus, onDidChangeTitleArea, paneStyler, onDidChange, onDidChangeVisibility); diff --git a/src/vs/workbench/contrib/codeEditor/browser/semanticTokensHelp.ts b/src/vs/workbench/contrib/codeEditor/browser/semanticTokensHelp.ts index 2eef853e00..7f497a288e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/semanticTokensHelp.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/semanticTokensHelp.ts @@ -16,6 +16,7 @@ import { ITextModel } from 'vs/editor/common/model'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; /** * Shows a message when semantic tokens are shown the first time. @@ -24,32 +25,34 @@ export class SemanticTokensHelp extends Disposable implements IEditorContributio public static readonly ID = 'editor.contrib.semanticHighlightHelp'; - private static notificationShown = false; - constructor( _editor: ICodeEditor, @INotificationService _notificationService: INotificationService, @IOpenerService _openerService: IOpenerService, @IWorkbenchThemeService _themeService: IWorkbenchThemeService, @IEditorService _editorService: IEditorService, + @IStorageService _storageService: IStorageService, @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - // opt-in to syncing const neverShowAgainId = 'editor.contrib.semanticTokensHelp'; + + if (_storageService.getBoolean(neverShowAgainId, StorageScope.GLOBAL)) { + return; + } + storageKeysSyncRegistryService.registerStorageKey({ key: neverShowAgainId, version: 1 }); const toDispose = this._register(new DisposableStore()); const localToDispose = toDispose.add(new DisposableStore()); const installChangeTokenListener = (model: ITextModel) => { localToDispose.add(model.onDidChangeTokens((e) => { - if (SemanticTokensHelp.notificationShown) { - toDispose.dispose(); + if (!e.semanticTokensApplied) { return; } - - if (!e.semanticTokensApplied) { + if (_storageService.getBoolean(neverShowAgainId, StorageScope.GLOBAL)) { + toDispose.dispose(); return; } const activeEditorControl = _editorService.activeTextEditorControl; @@ -58,7 +61,7 @@ export class SemanticTokensHelp extends Disposable implements IEditorContributio } toDispose.dispose(); // uninstall all listeners, make sure the notification is only shown once per window - SemanticTokensHelp.notificationShown = true; + _storageService.store(neverShowAgainId, true, StorageScope.GLOBAL); // never show again const message = nls.localize( { @@ -81,7 +84,7 @@ export class SemanticTokensHelp extends Disposable implements IEditorContributio _openerService.open(URI.parse(url)); } } - ], { neverShowAgain: { id: neverShowAgainId } }); + ]); })); }; diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index a5fcd53243..f5d014e46e 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -89,18 +89,11 @@ white-space: pre; } -.monaco-editor.vs-dark .review-widget .body .comment-body h4 { - margin: 0; -} .monaco-editor .review-widget .body .review-comment .review-comment-contents .author { line-height: 22px; } -.monaco-editor.vs-dark .review-widget .body .review-comment .review-comment-contents .author { - color: #fff; - font-weight: 600; -} .monaco-editor .review-widget .body .review-comment .review-comment-contents .isPending { margin: 0 5px 0 5px; @@ -108,7 +101,7 @@ font-style: italic; } -.monaco-editor.vs-dark .review-widget .body .review-comment .review-comment-contents .comment-body { +.monaco-editor .review-widget .body .review-comment .review-comment-contents .comment-body { padding-top: 4px; } @@ -183,10 +176,6 @@ opacity: 0.6; } -.monaco-editor.vs-dark .review-widget .body span.created_at { - color: #e0e0e0; -} - .monaco-editor .review-widget .body .comment-body p, .monaco-editor .review-widget .body .comment-body ul { margin: 8px 0; diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index b7cfcb4ff7..1b7dbfbe4a 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -27,7 +27,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { public static typeId = 'workbench.editors.webviewEditor'; private readonly _editorResource: URI; - private readonly _fromBackup: boolean; + private readonly _startsDirty: boolean | undefined; get resource() { return this._editorResource; } @@ -38,7 +38,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { viewType: string, id: string, webview: Lazy, - fromBackup: boolean, + options: { startsDirty?: boolean }, @IWebviewService webviewService: IWebviewService, @IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService, @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -51,7 +51,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { ) { super(id, viewType, '', webview, webviewService, webviewWorkbenchService); this._editorResource = resource; - this._fromBackup = fromBackup; + this._startsDirty = options.startsDirty; } public getTypeId(): string { @@ -110,7 +110,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { public isDirty(): boolean { if (!this._modelRef) { - return this._fromBackup; + return !!this._startsDirty; } return this._modelRef.object.isDirty(); } @@ -201,7 +201,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { this.viewType, this.id, new Lazy(() => undefined!), - this._fromBackup); // this webview is replaced in the transfer call + { startsDirty: this._startsDirty }); // this webview is replaced in the transfer call this.transfer(newEditor); newEditor.updateGroup(group); return newEditor; diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index c044311ee1..c65d88938a 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -11,7 +11,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IEditorInput } from 'vs/workbench/common/editor'; import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; -import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; +import { WebviewEditorInputFactory, SerializedWebview } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -30,6 +30,12 @@ export interface CustomDocumentBackupData { }; } +interface SerializedCustomEditor extends SerializedWebview { + readonly editorResource: UriComponents; + readonly dirty?: boolean; +} + + export class CustomEditorInputFactory extends WebviewEditorInputFactory { public static readonly ID = CustomEditorInput.typeId; @@ -43,9 +49,10 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory { } public serialize(input: CustomEditorInput): string | undefined { - const data = { + const data: SerializedCustomEditor = { ...this.toJson(input), editorResource: input.resource.toJSON(), + dirty: input.isDirty(), }; try { @@ -78,7 +85,7 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory { return webview; }); - const customInput = this._instantiationService.createInstance(CustomEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview, false); + const customInput = this._instantiationService.createInstance(CustomEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview, { startsDirty: (data as any).dirty }); if (typeof data.group === 'number') { customInput.updateGroup(data.group); } @@ -112,7 +119,7 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory { return webview; }); - const editor = instantiationService.createInstance(CustomEditorInput, URI.revive(backupData.editorResource), backupData.viewType, id, webview, true); + const editor = instantiationService.createInstance(CustomEditorInput, URI.revive(backupData.editorResource), backupData.viewType, id, webview, { startsDirty: true }); editor.updateGroup(0); return editor; }); diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index cc6431956b..4f06f7e7a2 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -23,7 +23,7 @@ import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { EditorInput, EditorOptions, GroupIdentifier, IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; -import { webviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint'; +import { webviewEditorsExtensionPoint, IWebviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint'; import { CONTEXT_CUSTOM_EDITORS, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CustomEditorInfo, CustomEditorInfoCollection, CustomEditorPriority, CustomEditorSelector, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; @@ -31,12 +31,16 @@ import { IWebviewService, webviewHasOwnEditFunctionsContext } from 'vs/workbench import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService'; import { CustomEditorInput } from './customEditorInput'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; export const defaultEditorId = 'default'; +const builtinProviderDisplayName = nls.localize('builtinProviderDisplayName', "Built-in"); + const defaultEditorInfo = new CustomEditorInfo({ id: defaultEditorId, - displayName: nls.localize('promptOpenWith.defaultEditor', "VS Code's standard text editor"), + displayName: nls.localize('promptOpenWith.defaultEditor.displayName', "Text Editor"), + providerDisplayName: builtinProviderDisplayName, selector: [ { filenamePattern: '*' } ], @@ -58,8 +62,9 @@ export class CustomEditorInfoStore extends Disposable { this.add(new CustomEditorInfo({ id: webviewEditorContribution.viewType, displayName: webviewEditorContribution.displayName, + providerDisplayName: extension.description.isBuiltin ? builtinProviderDisplayName : extension.description.displayName || extension.description.identifier.value, selector: webviewEditorContribution.selector || [], - priority: webviewEditorContribution.priority || CustomEditorPriority.default, + priority: getPriorityFromContribution(webviewEditorContribution, extension.description), })); } } @@ -192,6 +197,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ description: editorDescriptor.id === currentlyOpenedEditorType ? nls.localize('openWithCurrentlyActive', "Currently Active") : undefined, + detail: editorDescriptor.providerDisplayName, buttons: resourceExt ? [{ iconClass: 'codicon-settings-gear', tooltip: nls.localize('promptOpenWith.setDefaultTooltip', "Set as default editor for '{0}' files", resourceExt) @@ -269,7 +275,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ const webview = new Lazy(() => { return this.webviewService.createWebviewOverlay(id, { customClasses: options?.customClasses }, {}); }); - const input = this.instantiationService.createInstance(CustomEditorInput, resource, viewType, id, webview, false); + const input = this.instantiationService.createInstance(CustomEditorInput, resource, viewType, id, webview, {}); if (typeof group !== 'undefined') { input.updateGroup(group); } @@ -569,9 +575,29 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo } } +function getPriorityFromContribution( + contribution: IWebviewEditorsExtensionPoint, + extension: IExtensionDescription, +): CustomEditorPriority { + switch (contribution.priority) { + case CustomEditorPriority.default: + case CustomEditorPriority.option: + return contribution.priority; + + case CustomEditorPriority.builtin: + // Builtin is only valid for builtin extensions + return extension.isBuiltin ? CustomEditorPriority.builtin : CustomEditorPriority.default; + + default: + return CustomEditorPriority.default; + } +} + registerThemingParticipant((theme, collector) => { const shadow = theme.getColor(colorRegistry.scrollbarShadow); if (shadow) { collector.addRule(`.webview.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`); } }); + + diff --git a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts index 17cafa4be0..fa55b09afb 100644 --- a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts @@ -16,11 +16,11 @@ namespace WebviewEditorContribution { export const priority = 'priority'; } -interface IWebviewEditorsExtensionPoint { +export interface IWebviewEditorsExtensionPoint { readonly [WebviewEditorContribution.viewType]: string; readonly [WebviewEditorContribution.displayName]: string; readonly [WebviewEditorContribution.selector]?: readonly CustomEditorSelector[]; - readonly [WebviewEditorContribution.priority]?: CustomEditorPriority; + readonly [WebviewEditorContribution.priority]?: string; } const webviewEditorsContribution: IJSONSchema = { @@ -75,12 +75,10 @@ const webviewEditorsContribution: IJSONSchema = { enum: [ CustomEditorPriority.default, CustomEditorPriority.option, - CustomEditorPriority.builtin, ], markdownEnumDescriptions: [ nls.localize('contributes.priority.default', 'Editor is automatically used for a resource if no other default custom editors are registered for it.'), nls.localize('contributes.priority.option', 'Editor is not automatically used but can be selected by a user.'), - nls.localize('contributes.priority.builtin', 'Editor automatically used if no other `default` or `builtin` editors are registered for the resource.'), ], default: 'default' } diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index 90468a4e5c..1ea12f5c1a 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -7,6 +7,7 @@ import { distinct, mergeSort } from 'vs/base/common/arrays'; import { Event } from 'vs/base/common/event'; import * as glob from 'vs/base/common/glob'; import { IDisposable, IReference } from 'vs/base/common/lifecycle'; +import { posix } from 'vs/base/common/path'; import { basename } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -75,17 +76,20 @@ export class CustomEditorInfo { public readonly id: string; public readonly displayName: string; + public readonly providerDisplayName: string | undefined; public readonly priority: CustomEditorPriority; public readonly selector: readonly CustomEditorSelector[]; constructor(descriptor: { readonly id: string; readonly displayName: string; + readonly providerDisplayName: string | undefined; readonly priority: CustomEditorPriority; readonly selector: readonly CustomEditorSelector[]; }) { this.id = descriptor.id; this.displayName = descriptor.displayName; + this.providerDisplayName = descriptor.providerDisplayName; this.priority = descriptor.priority; this.selector = descriptor.selector; } @@ -96,7 +100,9 @@ export class CustomEditorInfo { static selectorMatches(selector: CustomEditorSelector, resource: URI): boolean { if (selector.filenamePattern) { - if (glob.match(selector.filenamePattern.toLowerCase(), basename(resource).toLowerCase())) { + const matchOnPath = selector.filenamePattern.indexOf(posix.sep) >= 0; + const target = matchOnPath ? resource.path : basename(resource); + if (glob.match(selector.filenamePattern.toLowerCase(), target.toLowerCase())) { return true; } } diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 041fba5d33..f7bd67752c 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -133,7 +133,11 @@ export class CallStackView extends ViewPane { this.needsRefresh = false; this.dataSource.deemphasizedStackFramesToShow = []; this.tree.updateChildren().then(() => { - this.parentSessionToExpand.forEach(s => this.tree.expand(s)); + try { + this.parentSessionToExpand.forEach(s => this.tree.expand(s)); + } catch (e) { + // Ignore tree expand errors if element no longer present + } this.parentSessionToExpand.clear(); if (this.selectionNeedsUpdate) { this.selectionNeedsUpdate = false; diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 1ba6dab657..db3974c008 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -44,7 +44,7 @@ import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl'; import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { DebugViewPaneContainer, OpenDebugPanelAction } from 'vs/workbench/contrib/debug/browser/debugViewlet'; +import { DebugViewPaneContainer, OpenDebugConsoleAction } from 'vs/workbench/contrib/debug/browser/debugViewlet'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { CallStackEditorContribution } from 'vs/workbench/contrib/debug/browser/callStackEditorContribution'; import { BreakpointEditorContribution } from 'vs/workbench/contrib/debug/browser/breakpointEditorContribution'; @@ -91,7 +91,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewE name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), focusCommand: { - id: OpenDebugPanelAction.ID, + id: OpenDebugConsoleAction.ID, keybindings: openPanelKb }, order: 3, @@ -120,7 +120,7 @@ registerCommands(); // register action to open viewlet const registry = Registry.as(WorkbenchActionRegistryExtensions.WorkbenchActions); -registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View")); +registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenDebugConsoleAction, OpenDebugConsoleAction.ID, OpenDebugConsoleAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View")); registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenDebugViewletAction, OpenDebugViewletAction.ID, OpenDebugViewletAction.LABEL, openViewletKb), 'View: Show Run and Debug', nls.localize('view', "View")); Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugToolBar, LifecyclePhase.Restored); @@ -173,7 +173,7 @@ Registry.as(QuickAccessExtensions.Quickaccess).registerQui prefix: StartDebugQuickAccessProvider.PREFIX, contextKey: 'inLaunchConfigurationsPicker', placeholder: nls.localize('startDebugPlaceholder', "Type the name of a launch configuration to run."), - helpEntries: [{ description: nls.localize('startDebugHelp', "Start Debug Configurations"), needsEditor: false }] + helpEntries: [{ description: nls.localize('startDebuggingHelp', "Start Debugging"), needsEditor: false }] }); // register service @@ -363,7 +363,7 @@ registerEditorContribution(BREAKPOINT_EDITOR_CONTRIBUTION_ID, BreakpointEditorCo MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { group: '4_panels', command: { - id: OpenDebugPanelAction.ID, + id: OpenDebugConsoleAction.ID, title: nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console") }, order: 2 diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index 4a6559d3df..67588416f4 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -346,7 +346,7 @@ export class ConfigurationManager implements IConfigurationManager { private setCompoundSchemaValues(): void { const compoundConfigurationsSchema = (launchSchema.properties!['compounds'].items).properties!['configurations']; const launchNames = this.launches.map(l => - l.getConfigurationNames(false)).reduce((first, second) => first.concat(second), []); + l.getConfigurationNames(true)).reduce((first, second) => first.concat(second), []); (compoundConfigurationsSchema.items).oneOf![0].enum = launchNames; (compoundConfigurationsSchema.items).oneOf![1].properties!.name.enum = launchNames; @@ -523,7 +523,7 @@ abstract class AbstractLaunch { return config.compounds.filter(compound => compound.name === name).pop(); } - getConfigurationNames(includeCompounds = true): string[] { + getConfigurationNames(ignoreCompoundsAndPresentation = false): string[] { const config = this.getConfig(); if (!config || (!Array.isArray(config.configurations) && !Array.isArray(config.compounds))) { return []; @@ -532,12 +532,14 @@ abstract class AbstractLaunch { if (config.configurations) { configurations.push(...config.configurations.filter(cfg => cfg && typeof cfg.name === 'string')); } - if (includeCompounds && config.compounds) { - if (config.compounds) { - configurations.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)); - } + + if (ignoreCompoundsAndPresentation) { + return configurations.map(c => c.name); } + if (config.compounds) { + configurations.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)); + } return getVisibleAndSorted(configurations).map(c => c.name); } } diff --git a/src/vs/workbench/contrib/debug/browser/debugProgress.ts b/src/vs/workbench/contrib/debug/browser/debugProgress.ts index 626676f460..33142707ae 100644 --- a/src/vs/workbench/contrib/debug/browser/debugProgress.ts +++ b/src/vs/workbench/contrib/debug/browser/debugProgress.ts @@ -43,17 +43,26 @@ export class DebugProgressContribution implements IWorkbenchContribution { source, delay: 500 }, progressStep => { - let increment = 0; + let total = 0; + const reportProgress = (progress: { message?: string, percentage?: number }) => { + let increment = undefined; + if (typeof progress.percentage === 'number') { + increment = progress.percentage - total; + total += increment; + } + progressStep.report({ + message: progress.message, + increment, + total: typeof increment === 'number' ? 100 : undefined, + }); + }; + + if (progressStartEvent.body.message) { + reportProgress(progressStartEvent.body); + } const progressUpdateListener = session.onDidProgressUpdate(e => { if (e.body.progressId === progressStartEvent.body.progressId) { - if (typeof e.body.percentage === 'number') { - increment = e.body.percentage - increment; - } - progressStep.report({ - message: e.body.message, - increment: typeof e.body.percentage === 'number' ? increment : undefined, - total: typeof e.body.percentage === 'number' ? 100 : undefined, - }); + reportProgress(e.body); } }); diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts index 078d5ff09b..671922c40a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts @@ -24,7 +24,11 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider this.commandService.executeCommand('debug.addConfiguration', launch.uri.toString()) diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index f2a5d989cb..563effa35f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -34,6 +34,7 @@ import { distinct } from 'vs/base/common/arrays'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { localize } from 'vs/nls'; +import { canceled } from 'vs/base/common/errors'; export class DebugSession implements IDebugSession { @@ -250,6 +251,9 @@ export class DebugSession implements IDebugSession { if (!this.raw) { throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'launch or attach')); } + if (this.parentSession && this.parentSession.state === State.Inactive) { + throw canceled(); + } // __sessionID only used for EH debugging (but we add it always for now...) config.__sessionId = this.getId(); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index afa0e78a87..32e9d99c70 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import { IAction } from 'vs/base/common/actions'; import * as DOM from 'vs/base/browser/dom'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, DEBUG_PANEL_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug'; import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -30,10 +30,9 @@ import { IMenu, MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; export class DebugViewPaneContainer extends ViewPaneContainer { @@ -107,8 +106,8 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } @memoize - private get toggleReplAction(): OpenDebugPanelAction { - return this._register(this.instantiationService.createInstance(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL)); + private get toggleReplAction(): OpenDebugConsoleAction { + return this._register(this.instantiationService.createInstance(OpenDebugConsoleAction, OpenDebugConsoleAction.ID, OpenDebugConsoleAction.LABEL)); } @memoize @@ -231,16 +230,18 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } } -export class OpenDebugPanelAction extends TogglePanelAction { +export class OpenDebugConsoleAction extends ToggleViewAction { public static readonly ID = 'workbench.debug.action.toggleRepl'; public static readonly LABEL = nls.localize('toggleDebugPanel', "Debug Console"); constructor( id: string, label: string, - @IPanelService panelService: IPanelService, + @IViewsService viewsService: IViewsService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, DEBUG_PANEL_ID, panelService, layoutService, 'codicon-repl'); + super(id, label, REPL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService, 'codicon-debug-console'); } } diff --git a/src/vs/workbench/contrib/debug/browser/welcomeView.ts b/src/vs/workbench/contrib/debug/browser/welcomeView.ts index 432b90c6fe..3e3ce4509e 100644 --- a/src/vs/workbench/contrib/debug/browser/welcomeView.ts +++ b/src/vs/workbench/contrib/debug/browser/welcomeView.ts @@ -75,6 +75,11 @@ export class WelcomeView extends ViewPane { }; this._register(editorService.onDidActiveEditorChange(setContextKey)); this._register(this.debugService.getConfigurationManager().onDidRegisterDebugger(setContextKey)); + this._register(this.onDidChangeBodyVisibility(visible => { + if (visible) { + setContextKey(); + } + })); setContextKey(); const debugKeybinding = this.keybindingService.lookupKeybinding(StartAction.ID); diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index fadaacd006..b72288ff2c 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -710,7 +710,7 @@ export interface ILaunch { * Returns the names of all configurations and compounds. * Ignores configurations which are invalid. */ - getConfigurationNames(includeCompounds?: boolean): string[]; + getConfigurationNames(ignoreCompoundsAndPresentation?: boolean): string[]; /** * Opens the launch.json file. Creates if it does not exist. diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index cbb910b758..c0405b4102 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -862,7 +862,15 @@ export class ExtensionEditor extends BaseEditor { extensionPackReadme.style.maxWidth = '882px'; const extensionPack = append(extensionPackReadme, $('div', { class: 'extension-pack' })); - toggleClass(extensionPackReadme, 'narrow', manifest.extensionPack!.length <= 2); + if (manifest.extensionPack!.length <= 3) { + addClass(extensionPackReadme, 'one-row'); + } else if (manifest.extensionPack!.length <= 6) { + addClass(extensionPackReadme, 'two-rows'); + } else if (manifest.extensionPack!.length <= 9) { + addClass(extensionPackReadme, 'three-rows'); + } else { + addClass(extensionPackReadme, 'more-rows'); + } const extensionPackHeader = append(extensionPack, $('div.header')); extensionPackHeader.textContent = localize('extension pack', "Extension Pack ({0})", manifest.extensionPack!.length); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 495bbccaaf..c37c98ffd0 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -2605,7 +2605,7 @@ export class MaliciousStatusLabelAction extends ExtensionAction { export class SyncIgnoredIconAction extends ExtensionAction { - private static readonly ENABLE_CLASS = `${ExtensionAction.ICON_ACTION_CLASS} codicon-eye-closed`; + private static readonly ENABLE_CLASS = `${ExtensionAction.ICON_ACTION_CLASS} codicon-sync-ignored`; private static readonly DISABLE_CLASS = `${SyncIgnoredIconAction.ENABLE_CLASS} hide`; constructor( diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts index 07ddbbc7a1..6a33de0280 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts @@ -54,7 +54,7 @@ export class ExtensionsGridView extends Disposable { private renderExtension(extension: IExtension, index: number): void { const extensionContainer = dom.append(this.element, dom.$('.extension-container')); extensionContainer.style.height = `${this.delegate.getHeight()}px`; - extensionContainer.style.width = `350px`; + extensionContainer.style.width = `275px`; extensionContainer.setAttribute('tabindex', '0'); const template = this.renderer.renderTemplate(extensionContainer); diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionActions.css b/src/vs/workbench/contrib/extensions/browser/media/extensionActions.css index f284f62df9..128f42854b 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionActions.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionActions.css @@ -55,6 +55,7 @@ .monaco-action-bar .action-item.disabled .action-label.extension-action { opacity: 1; + pointer-events: none; } .monaco-action-bar .action-item.disabled .action-label.extension-action.text { diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css index 733951193f..15d110b7be 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css @@ -277,16 +277,36 @@ padding-left: 20px; } -.extension-editor > .body > .content > .extension-pack-readme.narrow > .extension-pack { +.extension-editor > .body > .content > .extension-pack-readme.one-row > .extension-pack { height: 142px; } -.extension-editor > .body > .content > .extension-pack-readme > .readme-content { +.extension-editor > .body > .content > .extension-pack-readme.two-rows > .extension-pack { + height: 224px; +} + +.extension-editor > .body > .content > .extension-pack-readme.three-rows > .extension-pack { + height: 306px; +} + +.extension-editor > .body > .content > .extension-pack-readme.more-rows > .extension-pack { + height: 326px; +} + +.extension-editor > .body > .content > .extension-pack-readme.one-row > .readme-content { + height: calc(100% - 142px); +} + +.extension-editor > .body > .content > .extension-pack-readme.two-rows > .readme-content { height: calc(100% - 224px); } -.extension-editor > .body > .content > .extension-pack-readme.narrow > .readme-content { - height: calc(100% - 142px); +.extension-editor > .body > .content > .extension-pack-readme.three-rows > .readme-content { + height: calc(100% - 306px); +} + +.extension-editor > .body > .content > .extension-pack-readme.more-rows > .readme-content { + height: calc(100% - 326px); } .extension-editor > .body > .content > .extension-pack-readme > .extension-pack > .header, @@ -483,6 +503,12 @@ cursor: pointer; } +.extension-editor .extensions-grid-view .extension-list-item > .details > .header-container > .header > .version, +.extension-editor .extensions-grid-view .extension-list-item > .details > .header-container > .header > .ratings, +.extension-editor .extensions-grid-view .extension-list-item > .details > .header-container > .header > .install-count { + display: none; +} + .extension-editor .extensions-grid-view > .extension-container:focus > .extension-list-item > .details .header > .name, .extension-editor .extensions-grid-view > .extension-container:focus > .extension-list-item > .details .header > .name:hover { text-decoration: underline; diff --git a/src/vs/workbench/contrib/files/browser/views/emptyView.ts b/src/vs/workbench/contrib/files/browser/views/emptyView.ts index 41a9714e57..07aac3e2df 100644 --- a/src/vs/workbench/contrib/files/browser/views/emptyView.ts +++ b/src/vs/workbench/contrib/files/browser/views/emptyView.ts @@ -89,8 +89,4 @@ export class EmptyView extends ViewPane { this.updateTitle(this.title); } } - - layoutBody(_size: number): void { - // no-op - } } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 186d881cab..b2db79a487 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -499,7 +499,13 @@ export class ExplorerView extends ViewPane { const actions: IAction[] = []; const roots = this.explorerService.roots; // If the click is outside of the elements pass the root resource if there is only one root. If there are multiple roots pass empty object. - const arg = stat instanceof ExplorerItem ? stat.resource : roots.length === 1 ? roots[0].resource : {}; + let arg: URI | {}; + if (stat instanceof ExplorerItem) { + const compressedController = this.renderer.getCompressedNavigationController(stat); + arg = compressedController ? compressedController.current.resource : stat.resource; + } else { + arg = roots.length === 1 ? roots[0].resource : {}; + } disposables.add(createAndFillInContextMenuActions(this.contributedContextMenu, { arg, shouldForwardArgs: true }, actions, this.contextMenuService)); this.contextMenuService.showContextMenu({ diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index adf2ca063d..8f1c9655b1 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -4,9 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/workbench/contrib/markers/browser/markersFileDecorations'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; @@ -14,7 +13,6 @@ import { localize } from 'vs/nls'; import { Marker, RelatedInformation } from 'vs/workbench/contrib/markers/browser/markersModel'; import { MarkersView } from 'vs/workbench/contrib/markers/browser/markersView'; import { MenuId, MenuRegistry, SyncActionDescriptor, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowProblemsPanelAction } from 'vs/workbench/contrib/markers/browser/markersViewActions'; import Constants from 'vs/workbench/contrib/markers/browser/constants'; @@ -28,11 +26,12 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar'; import { IMarkerService, MarkerStatistics } from 'vs/platform/markers/common/markers'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewsRegistry, IViewsService, getVisbileViewContextKey, FocusedViewContext } from 'vs/workbench/common/views'; +import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewsRegistry, IViewsService, getVisbileViewContextKey, FocusedViewContext, IViewDescriptorService } from 'vs/workbench/common/views'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import type { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false); @@ -94,16 +93,18 @@ Registry.as(Extensions.Configuration).registerConfigurat } }); -class ToggleMarkersPanelAction extends TogglePanelAction { +class ToggleMarkersPanelAction extends ToggleViewAction { public static readonly ID = 'workbench.actions.view.problems'; public static readonly LABEL = Messages.MARKERS_PANEL_TOGGLE_LABEL; constructor(id: string, label: string, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @IPanelService panelService: IPanelService + @IViewsService viewsService: IViewsService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService ) { - super(id, label, Constants.MARKERS_CONTAINER_ID, panelService, layoutService); + super(id, label, Constants.MARKERS_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); } } diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 8553e9ae7c..dba6cf44ed 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -3,26 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'workbench.notebook.code.insertCellAbove'; -export const INSERT_CODE_CELL_BELOW_COMMAND_ID = 'workbench.notebook.code.insertCellBelow'; -export const INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID = 'workbench.notebook.markdown.insertCellAbove'; -export const INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID = 'workbench.notebook.markdown.insertCellBelow'; - -export const EDIT_CELL_COMMAND_ID = 'workbench.notebook.cell.edit'; -export const SAVE_CELL_COMMAND_ID = 'workbench.notebook.cell.save'; -export const DELETE_CELL_COMMAND_ID = 'workbench.notebook.cell.delete'; - -export const MOVE_CELL_UP_COMMAND_ID = 'workbench.notebook.cell.moveUp'; -export const MOVE_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.moveDown'; -export const COPY_CELL_UP_COMMAND_ID = 'workbench.notebook.cell.copyUp'; -export const COPY_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.copyDown'; - -export const EXECUTE_CELL_COMMAND_ID = 'workbench.notebook.cell.execute'; -export const EXECUTE_ACTIVE_CELL_COMMAND_ID = 'workbench.notebook.cell.executeActive'; -export const CANCEL_CELL_COMMAND_ID = 'workbench.notebook.cell.cancelExecution'; -export const EXECUTE_NOTEBOOK_COMMAND_ID = 'workbench.notebook.executeNotebook'; -export const CANCEL_NOTEBOOK_COMMAND_ID = 'workbench.notebook.cancelExecution'; - // Cell sizing related export const CELL_MARGIN = 20; export const CELL_RUN_GUTTER = 32; // TODO should be dynamic based on execution order width, and runnable enablement diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts index 6617b46003..b2f531c1ed 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts @@ -12,11 +12,33 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo import { InputFocusedContext, InputFocusedContextKey, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { CANCEL_CELL_COMMAND_ID, CANCEL_NOTEBOOK_COMMAND_ID, COPY_CELL_DOWN_COMMAND_ID, COPY_CELL_UP_COMMAND_ID, DELETE_CELL_COMMAND_ID, EDIT_CELL_COMMAND_ID, EXECUTE_ACTIVE_CELL_COMMAND_ID, EXECUTE_CELL_COMMAND_ID, EXECUTE_NOTEBOOK_COMMAND_ID, INSERT_CODE_CELL_ABOVE_COMMAND_ID, INSERT_CODE_CELL_BELOW_COMMAND_ID, INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID, INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, MOVE_CELL_DOWN_COMMAND_ID, MOVE_CELL_UP_COMMAND_ID, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_EDITABLE_CONTEXT_KEY, NOTEBOOK_EXECUTING_KEY, SAVE_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/constants'; +import { NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_EDITABLE_CONTEXT_KEY, NOTEBOOK_EXECUTING_KEY } from 'vs/workbench/contrib/notebook/browser/constants'; import { BaseCellRenderTemplate, CellEditState, CellRunState, ICellViewModel, INotebookEditor, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'workbench.notebook.code.insertCellAbove'; +const INSERT_CODE_CELL_BELOW_COMMAND_ID = 'workbench.notebook.code.insertCellBelow'; +const INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID = 'workbench.notebook.markdown.insertCellAbove'; +const INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID = 'workbench.notebook.markdown.insertCellBelow'; + +const EDIT_CELL_COMMAND_ID = 'workbench.notebook.cell.edit'; +const SAVE_CELL_COMMAND_ID = 'workbench.notebook.cell.save'; +const DELETE_CELL_COMMAND_ID = 'workbench.notebook.cell.delete'; + +const MOVE_CELL_UP_COMMAND_ID = 'workbench.notebook.cell.moveUp'; +const MOVE_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.moveDown'; +const COPY_CELL_UP_COMMAND_ID = 'workbench.notebook.cell.copyUp'; +const COPY_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.copyDown'; + +const EXECUTE_CELL_COMMAND_ID = 'workbench.notebook.cell.execute'; +const EXECUTE_ACTIVE_CELL_COMMAND_ID = 'workbench.notebook.cell.executeActive'; +const CANCEL_CELL_COMMAND_ID = 'workbench.notebook.cell.cancelExecution'; +const EXECUTE_NOTEBOOK_COMMAND_ID = 'workbench.notebook.executeNotebook'; +const CANCEL_NOTEBOOK_COMMAND_ID = 'workbench.notebook.cancelExecution'; + +const NOTEBOOK_ACTIONS_CATEGORY = localize('notebookActions.category', "Notebook"); + const enum CellToolbarOrder { MoveCellUp, MoveCellDown, @@ -30,7 +52,8 @@ registerAction2(class extends Action2 { constructor() { super({ id: EXECUTE_CELL_COMMAND_ID, - title: localize('notebookActions.execute', "Execute Notebook Cell"), + category: NOTEBOOK_ACTIONS_CATEGORY, + title: localize('notebookActions.execute', "Execute Cell"), keybinding: { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, InputFocusedContext), primary: KeyMod.WinCtrl | KeyCode.Enter, @@ -39,7 +62,8 @@ registerAction2(class extends Action2 { }, weight: KeybindingWeight.WorkbenchContrib }, - icon: { id: 'codicon/play' } + icon: { id: 'codicon/play' }, + f1: true }); } @@ -59,8 +83,8 @@ registerAction2(class extends Action2 { constructor() { super({ id: CANCEL_CELL_COMMAND_ID, - title: localize('notebookActions.cancel', "Cancel Execution"), - icon: { id: 'codicon/stop' } + title: localize('notebookActions.cancel', "Stop Execution"), + icon: { id: 'codicon/primitive-square' } }); } @@ -103,7 +127,7 @@ export class CancelCellAction extends MenuItemAction { { id: CANCEL_CELL_COMMAND_ID, title: localize('notebookActions.CancelCell', "Cancel Execution"), - icon: { id: 'codicon/stop' } + icon: { id: 'codicon/primitive-square' } }, undefined, { shouldForwardArgs: true }, @@ -331,8 +355,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CANCEL_NOTEBOOK_COMMAND_ID, - title: localize('notebookActions.menu.cancelNotebook', "Cancel Notebook Execution"), - icon: { id: 'codicon/stop' } + title: localize('notebookActions.menu.cancelNotebook', "Stop Notebook Execution"), + icon: { id: 'codicon/primitive-square' } }, order: -1, group: 'navigation', @@ -346,7 +370,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { title: localize('notebookActions.menu.execute', "Execute Notebook Cell"), icon: { id: 'codicon/run' } }, - order: -1, + order: 0, group: 'navigation', when: NOTEBOOK_EDITOR_FOCUSED }); @@ -387,7 +411,7 @@ registerAction2(class extends Action2 { } }); -function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor | undefined { +export function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor | undefined { // TODO can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? const activeEditorPane = editorService.activeEditorPane as any | undefined; return activeEditorPane?.isNotebookEditor ? activeEditorPane : undefined; @@ -531,6 +555,7 @@ registerAction2(class extends InsertCellCommand { { id: INSERT_CODE_CELL_BELOW_COMMAND_ID, title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below"), + category: NOTEBOOK_ACTIONS_CATEGORY, icon: { id: 'codicon/add' }, menu: { id: MenuId.NotebookCellTitle, @@ -541,7 +566,8 @@ registerAction2(class extends InsertCellCommand { icon: { id: 'codicon/add' }, }, when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) - } + }, + f1: true }, CellKind.Code, 'below'); @@ -661,12 +687,14 @@ registerAction2(class extends Action2 { { id: DELETE_CELL_COMMAND_ID, title: localize('notebookActions.deleteCell', "Delete Cell"), + category: NOTEBOOK_ACTIONS_CATEGORY, menu: { id: MenuId.NotebookCellTitle, order: CellToolbarOrder.DeleteCell, when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) }, - icon: { id: 'codicon/trash' } + icon: { id: 'codicon/trash' }, + f1: true }); } @@ -700,6 +728,7 @@ registerAction2(class extends Action2 { { id: MOVE_CELL_UP_COMMAND_ID, title: localize('notebookActions.moveCellUp', "Move Cell Up"), + category: NOTEBOOK_ACTIONS_CATEGORY, icon: { id: 'codicon/arrow-up' }, menu: { id: MenuId.NotebookCellTitle, @@ -711,6 +740,7 @@ registerAction2(class extends Action2 { }, when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) }, + f1: true }); } @@ -732,6 +762,7 @@ registerAction2(class extends Action2 { { id: MOVE_CELL_DOWN_COMMAND_ID, title: localize('notebookActions.moveCellDown', "Move Cell Down"), + category: NOTEBOOK_ACTIONS_CATEGORY, icon: { id: 'codicon/arrow-down' }, menu: { id: MenuId.NotebookCellTitle, @@ -743,6 +774,7 @@ registerAction2(class extends Action2 { }, when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) }, + f1: true }); } @@ -950,6 +982,7 @@ registerAction2(class extends Action2 { super({ id: 'workbench.action.notebook.testResize', title: 'Notebook Test Cell Resize', + category: NOTEBOOK_ACTIONS_CATEGORY, keybinding: { when: IsDevelopmentContext, primary: undefined, diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 1bf2f684e5..6e781cc961 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -27,7 +27,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { IDisposable } from 'vs/base/common/lifecycle'; import { assertType } from 'vs/base/common/types'; import { parse } from 'vs/base/common/marshalling'; -import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellUri, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ResourceMap } from 'vs/base/common/map'; // Output renderers registration @@ -177,10 +177,11 @@ class CellContentProvider implements ITextModelContentProvider { } for (let cell of notebook.cells) { if (cell.uri.toString() === resource.toString()) { - let bufferFactory = cell.resolveTextBufferFactory(); + const bufferFactory = cell.resolveTextBufferFactory(); + const language = cell.cellKind === CellKind.Markdown ? this._modeService.create('markdown') : (cell.language ? this._modeService.create(cell.language) : this._modeService.createByFilepathOrFirstLine(resource, cell.source[0])); return this._modelService.createModel( bufferFactory, - cell.language ? this._modeService.create(cell.language) : this._modeService.createByFilepathOrFirstLine(resource, cell.source[0]), + language, resource ); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.css b/src/vs/workbench/contrib/notebook/browser/notebook.css index 65b3451375..20899957f1 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/notebook.css @@ -30,6 +30,11 @@ position: relative; } +.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container .webview-cover { + position: absolute; + top: 0; +} + .monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell { display: flex; } @@ -206,6 +211,8 @@ position: absolute; display: flex; opacity: 0; + transition: opacity 0.2s ease-in-out; + cursor: auto; } .monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container:hover { @@ -230,6 +237,7 @@ align-self: center; align-items: center; white-space: pre; + cursor: pointer; } .monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container span.codicon { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index f406a19b9f..3eab30505d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -18,6 +18,7 @@ import { NOTEBOOK_EDITABLE_CONTEXT_KEY, NOTEBOOK_EXECUTING_KEY } from 'vs/workbe import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); @@ -59,11 +60,14 @@ export interface CodeCellLayoutChangeEvent { export interface MarkdownCellLayoutInfo { readonly fontInfo: BareFontInfo | null; readonly editorWidth: number; + readonly bottomToolbarOffset: number; + readonly totalHeight: number; } export interface MarkdownCellLayoutChangeEvent { font?: BareFontInfo; outerWidth?: number; + totalHeight?: number; } export interface ICellViewModel { @@ -89,6 +93,8 @@ export interface INotebookEditor { isNotebookEditor: boolean; + getInnerWebview(): Webview | undefined; + /** * Focus the notebook editor cell list */ @@ -268,6 +274,7 @@ export interface BaseCellRenderTemplate { toolbar: ToolBar; focusIndicator: HTMLElement; disposables: DisposableStore; + bottomCellContainer: HTMLElement; toJSON: () => any; } @@ -283,7 +290,6 @@ export interface CodeCellRenderTemplate extends BaseCellRenderTemplate { outputContainer: HTMLElement; editor: CodeEditorWidget; progressBar: ProgressBar; - betweenCellContainer: HTMLElement; } export interface IOutputTransformContribution { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 25514ff4ec..242a99baa3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -5,7 +5,7 @@ import { getZoomLevel } from 'vs/base/browser/browser'; import * as DOM from 'vs/base/browser/dom'; -import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; +import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Color, RGBA } from 'vs/base/common/color'; import { Emitter, Event } from 'vs/base/common/event'; @@ -43,6 +43,7 @@ import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewStat import { CellKind, CellUri, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; const $ = DOM.$; const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState'; @@ -91,6 +92,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { private rootElement!: HTMLElement; private body!: HTMLElement; private webview: BackLayerWebView | null = null; + private webviewTransparentCover: HTMLElement | null = null; private list: NotebookCellList | undefined; private control: ICompositeCodeEditor | undefined; private renderedEditors: Map = new Map(); @@ -231,13 +233,36 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } })); this.list.rowsContainer.appendChild(this.webview.element); + this._register(this.list); + + // transparent cover + this.webviewTransparentCover = DOM.append(this.list.rowsContainer, $('.webview-cover')); + this.webviewTransparentCover.style.display = 'none'; + + this._register(DOM.addStandardDisposableGenericMouseDownListner(this.rootElement, (e: StandardMouseEvent) => { + if (DOM.hasClass(e.target, 'slider') && this.webviewTransparentCover) { + this.webviewTransparentCover.style.display = 'block'; + } + })); + + this._register(DOM.addStandardDisposableGenericMouseUpListner(this.rootElement, (e: StandardMouseEvent) => { + if (this.webviewTransparentCover) { + // no matter when + this.webviewTransparentCover.style.display = 'none'; + } + })); + } getControl() { return this.control; } + getInnerWebview(): Webview | undefined { + return this.webview?.webview; + } + onHide() { this.editorFocus?.set(false); if (this.webview) { @@ -290,6 +315,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const cellOptions = options.cellOptions; const cell = this.notebookViewModel!.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { + this.selectElement(cell); this.revealInCenterIfOutsideViewport(cell); const editor = this.renderedEditors.get(cell)!; if (editor) { @@ -324,6 +350,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.webview?.clearInsets(); this.webview?.clearPreloadsCache(); this.findWidget.clear(); + this.list?.splice(0, this.list?.length || 0); } private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) { @@ -339,14 +366,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const viewState = this.loadTextEditorViewState(input); this.notebookViewModel.restoreEditorViewState(viewState); - if (viewState?.scrollPosition !== undefined) { - this.list!.scrollTop = viewState!.scrollPosition.top; - this.list!.scrollLeft = viewState!.scrollPosition.left; - } else { - this.list!.scrollTop = 0; - this.list!.scrollLeft = 0; - } - this.localStore.add(this.eventDispatcher.onDidChangeMetadata((e) => { this.editorEditable?.set(e.source.editable); })); @@ -385,6 +404,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.localStore.add(this.list!.onWillScroll(e => { this.webview!.updateViewScrollTop(-e.scrollTop, []); + this.webviewTransparentCover!.style.top = `${e.scrollTop}px`; })); this.localStore.add(this.list!.onDidChangeContentHeight(() => { @@ -413,9 +433,16 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } })); - this.list?.splice(0, this.list?.length || 0); this.list?.splice(0, 0, this.notebookViewModel!.viewCells as CellViewModel[]); this.list?.layout(); + + if (viewState?.scrollPosition !== undefined) { + this.list!.scrollTop = viewState!.scrollPosition.top; + this.list!.scrollLeft = viewState!.scrollPosition.left; + } else { + this.list!.scrollTop = 0; + this.list!.scrollLeft = 0; + } } private saveTextEditorViewState(input: NotebookEditorInput): void { @@ -423,6 +450,17 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const state = this.notebookViewModel.saveEditorViewState(); if (this.list) { state.scrollPosition = { left: this.list.scrollLeft, top: this.list.scrollTop }; + let cellHeights: { [key: number]: number } = {}; + for (let i = 0; i < this.list.length; i++) { + const elm = this.list.element(i)!; + if (elm.cellKind === CellKind.Code) { + cellHeights[i] = elm.layoutInfo.totalHeight; + } else { + cellHeights[i] = 0; + } + } + + state.cellTotalHeights = cellHeights; } this.editorMemento.saveEditorState(this.group, input.resource, state); @@ -444,6 +482,12 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { DOM.size(this.body, dimension.width, dimension.height); this.list?.updateOptions({ additionalScrollHeight: dimension.height }); this.list?.layout(dimension.height, dimension.width); + + if (this.webviewTransparentCover) { + this.webviewTransparentCover.style.height = `${dimension.height}px`; + this.webviewTransparentCover.style.width = `${dimension.width}px`; + } + this.eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index d93a7fd48f..ccca6a0d04 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -123,6 +123,14 @@ export class NotebookCellList extends WorkbenchList implements ID return this.view.elementTop(index); } + getElementHeight(index: number): number { + if (index < 0 || index >= this.length) { + throw new ListError(this.listUser, `Invalid index ${index}`); + } + + return this.view.elementHeight(index); + } + triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) { this.view.triggerScrollFromMouseWheelEvent(browserEvent); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts index 809cabd5bf..5a5fa98ff6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IRenderOutput, CellOutputKind, IErrorOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { registerOutputTransform } from 'vs/workbench/contrib/notebook/browser/notebookRegistry'; import * as DOM from 'vs/base/browser/dom'; import { RGBA, Color } from 'vs/base/common/color'; @@ -18,7 +18,15 @@ class ErrorTransform implements IOutputTransformContribution { ) { } - render(output: any, container: HTMLElement): IRenderOutput { + render(output: IErrorOutput, container: HTMLElement): IRenderOutput { + const header = document.createElement('div'); + const headerMessage = output.ename && output.evalue + ? `${output.ename}: ${output.evalue}` + : output.ename || output.evalue; + if (headerMessage) { + header.innerText = headerMessage; + container.appendChild(header); + } const traceback = document.createElement('pre'); DOM.addClasses(traceback, 'traceback'); if (output.traceback) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 6f6193f6ca..77b9307cd3 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -5,9 +5,9 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; +import * as path from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -26,6 +26,12 @@ export interface IDimentionMessage { data: DOM.Dimension; } +export interface IWheelMessage { + __vscode_notebook_message: boolean; + type: 'did-scroll-wheel'; + payload: any; +} + export interface IScrollAckMessage { __vscode_notebook_message: boolean; @@ -73,7 +79,7 @@ export interface IUpdatePreloadResourceMessage { resources: string[]; } -type IMessage = IDimentionMessage | IScrollAckMessage; +type IMessage = IDimentionMessage | IScrollAckMessage | IWheelMessage; let version = 0; export class BackLayerWebView extends Disposable { @@ -92,7 +98,6 @@ export class BackLayerWebView extends Disposable { public notebookEditor: INotebookEditor, @IWebviewService webviewService: IWebviewService, @IOpenerService openerService: IOpenerService, - @IEnvironmentService private readonly environmentSerice: IEnvironmentService, @INotebookService private readonly notebookService: INotebookService, ) { super(); @@ -186,6 +191,45 @@ export class BackLayerWebView extends Disposable { observers.push(resizeObserver); } + function scrollWillGoToParent(event) { + for (let node = event.target; node; node = node.parentNode) { + if (node.id === 'container') { + return false; + } + + if (event.deltaY < 0 && node.scrollTop > 0) { + return true; + } + + if (event.deltaY > 0 && node.scrollTop + node.clientHeight < node.scrollHeight) { + return true; + } + } + + return false; + } + + const handleWheel = (event) => { + if (event.defaultPrevented || scrollWillGoToParent(event)) { + return; + } + + vscode.postMessage({ + __vscode_notebook_message: true, + type: 'did-scroll-wheel', + payload: { + deltaMode: event.deltaMode, + deltaX: event.deltaX, + deltaY: event.deltaY, + deltaZ: event.deltaZ, + detail: event.detail, + type: event.type + } + }); + }; + + window.addEventListener('wheel', handleWheel); + window.addEventListener('message', event => { let id = event.data.id; @@ -276,10 +320,6 @@ export class BackLayerWebView extends Disposable { openerService.open(link, { fromUserGesture: true }); })); - this._register(this.webview.onDidWheel(e => { - this.notebookEditor.triggerScroll(e); - })); - this._register(this.webview.onMessage((data: IMessage) => { if (data.__vscode_notebook_message) { if (data.type === 'dimension') { @@ -302,6 +342,8 @@ export class BackLayerWebView extends Disposable { // const date = new Date(); // const top = data.data.top; // console.log('ack top ', top, ' version: ', data.version, ' - ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds()); + } else if (data.type === 'did-scroll-wheel') { + this.notebookEditor.triggerScroll(data.payload); } return; } @@ -311,7 +353,8 @@ export class BackLayerWebView extends Disposable { } private _createInset(webviewService: IWebviewService, content: string) { - this.localResourceRootsCache = [...this.notebookService.getNotebookProviderResourceRoots(), URI.file(this.environmentSerice.appRoot)]; + const rootPath = URI.file(path.dirname(getPathFromAmdModule(require, ''))); + this.localResourceRootsCache = [...this.notebookService.getNotebookProviderResourceRoots(), rootPath]; const webview = webviewService.createWebviewElement('' + UUID.generateUuid(), { enableFindWidget: false, }, { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 25eb530ed9..e672c2cf65 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -84,6 +84,7 @@ export class CodiconActionViewItem extends ContextAwareMenuEntryActionViewItem { abstract class AbstractCellRenderer { protected editorOptions: IEditorOptions; + private actionRunner = new ActionRunner(); constructor( protected readonly instantiationService: IInstantiationService, @@ -138,6 +139,45 @@ abstract class AbstractCellRenderer { return toolbar; } + protected setupBetweenCellToolbarActions(element: CodeCellViewModel | MarkdownCellViewModel, templateData: BaseCellRenderTemplate, disposables: DisposableStore, context: INotebookCellActionContext): void { + const container = templateData.bottomCellContainer; + container.innerHTML = ''; + container.style.height = `${BOTTOM_CELL_TOOLBAR_HEIGHT}px`; + + DOM.append(container, $('.seperator')); + const addCodeCell = DOM.append(container, $('span.button')); + addCodeCell.innerHTML = renderCodicons(escape(`$(add) Code `)); + const insertCellBelow = this.instantiationService.createInstance(InsertCodeCellAction); + + disposables.add(DOM.addDisposableListener(addCodeCell, DOM.EventType.CLICK, () => { + this.actionRunner.run(insertCellBelow, context); + })); + + DOM.append(container, $('.seperator-short')); + const addMarkdownCell = DOM.append(container, $('span.button')); + addMarkdownCell.innerHTML = renderCodicons(escape('$(add) Markdown ')); + const insertMarkdownBelow = this.instantiationService.createInstance(InsertMarkdownCellAction); + disposables.add(DOM.addDisposableListener(addMarkdownCell, DOM.EventType.CLICK, () => { + this.actionRunner.run(insertMarkdownBelow, context); + })); + + DOM.append(container, $('.seperator')); + + if (element instanceof CodeCellViewModel) { + const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset; + container.style.top = `${bottomToolbarOffset}px`; + + disposables.add(element.onDidChangeLayout(() => { + const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset; + container.style.top = `${bottomToolbarOffset}px`; + })); + } else { + container.style.position = 'static'; + container.style.height = '22px'; + } + + } + protected createToolbar(container: HTMLElement): ToolBar { const toolbar = new ToolBar(container, this.contextMenuService, { actionViewItemProvider: action => { @@ -226,6 +266,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR container.appendChild(innerContent); const focusIndicator = DOM.append(container, DOM.$('.notebook-cell-focus-indicator')); + const bottomCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container')); return { container, @@ -234,6 +275,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR focusIndicator, disposables, toolbar, + bottomCellContainer: bottomCellContainer, toJSON: () => { return {}; } }; } @@ -258,9 +300,16 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR const contextKeyService = this.contextKeyService.createScoped(templateData.container); contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown'); contextKeyService.createKey(NOTEBOOK_VIEW_TYPE, element.viewType); + const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable)); + const updateForMetadata = () => { + const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel!.notebookDocument.metadata); + cellEditableKey.set(!!metadata.editable); + }; + + updateForMetadata(); elementDisposable.add(element.onDidChangeMetadata(() => { - cellEditableKey.set(!!element.metadata?.editable); + updateForMetadata(); })); const editModeKey = contextKeyService.createKey(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, element.editState === CellEditState.Editing); @@ -269,13 +318,18 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR })); this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable); + + const toolbarContext = { + cell: element, + notebookEditor: this.notebookEditor, + $mid: 12 + }; + templateData.toolbar.context = toolbarContext; + + this.setupBetweenCellToolbarActions(element, templateData, elementDisposable, toolbarContext); + element.totalHeight = height; } - templateData.toolbar.context = { - cell: element, - notebookEditor: this.notebookEditor, - $mid: 12 - }; } disposeTemplate(templateData: MarkdownCellRenderTemplate): void { @@ -292,8 +346,6 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR export class CodeCellRenderer extends AbstractCellRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'code_cell'; private disposables: Map = new Map(); - private actionRunner = new ActionRunner(); - constructor( protected notebookEditor: INotebookEditor, @@ -322,7 +374,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende const runToolbar = this.createToolbar(runButtonContainer); disposables.add(runToolbar); - const betweenCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container')); + const bottomCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container')); const executionOrderLabel = DOM.append(runButtonContainer, $('div.execution-count-label')); @@ -358,44 +410,11 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende outputContainer, editor, disposables, - betweenCellContainer: betweenCellContainer, + bottomCellContainer: bottomCellContainer, toJSON: () => { return {}; } }; } - protected setupBetweenCellToolbarActions(element: CodeCellViewModel, templateData: CodeCellRenderTemplate, disposables: DisposableStore, context: INotebookCellActionContext): void { - const container = templateData.betweenCellContainer; - container.innerHTML = ''; - container.style.height = `${BOTTOM_CELL_TOOLBAR_HEIGHT}px`; - - DOM.append(container, $('.seperator')); - const addCodeCell = DOM.append(container, $('span.button')); - addCodeCell.innerHTML = renderCodicons(escape(`$(add) Code `)); - const insertCellBelow = this.instantiationService.createInstance(InsertCodeCellAction); - - disposables.add(DOM.addDisposableListener(addCodeCell, DOM.EventType.CLICK, () => { - this.actionRunner.run(insertCellBelow, context); - })); - - DOM.append(container, $('.seperator-short')); - const addMarkdownCell = DOM.append(container, $('span.button')); - addMarkdownCell.innerHTML = renderCodicons(escape('$(add) Markdown ')); - const insertMarkdownBelow = this.instantiationService.createInstance(InsertMarkdownCellAction); - disposables.add(DOM.addDisposableListener(addMarkdownCell, DOM.EventType.CLICK, () => { - this.actionRunner.run(insertMarkdownBelow, context); - })); - - DOM.append(container, $('.seperator')); - - const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset; - container.style.top = `${bottomToolbarOffset}px`; - - disposables.add(element.onDidChangeLayout(() => { - const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset; - container.style.top = `${bottomToolbarOffset}px`; - })); - } - private updateForRunState(element: CodeCellViewModel, templateData: CodeCellRenderTemplate, runStateKey: IContextKey): void { runStateKey.set(CellRunState[element.runState]); if (element.runState === CellRunState.Running) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index ab7a46ae2b..620d1c769d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -6,7 +6,6 @@ import * as DOM from 'vs/base/browser/dom'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { debounce } from 'vs/base/common/decorators'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IModeService } from 'vs/editor/common/services/modeService'; import * as nls from 'vs/nls'; @@ -45,7 +44,7 @@ export class CodeCell extends Disposable { height: totalHeight } ); - viewCell.editorHeight = totalHeight; + // viewCell.editorHeight = totalHeight; const cts = new CancellationTokenSource(); this._register({ dispose() { cts.dispose(true); } }); @@ -211,6 +210,12 @@ export class CodeCell extends Disposable { })); if (viewCell.outputs.length > 0) { + let layoutCache = false; + if (this.viewCell.layoutInfo.totalHeight !== 0) { + layoutCache = true; + this.relayoutCell(); + } + this.templateData.outputContainer!.style.display = 'block'; // there are outputs, we need to calcualte their sizes and trigger relayout // @todo, if there is no resizable output, we should not check their height individually, which hurts the performance @@ -222,9 +227,15 @@ export class CodeCell extends Disposable { } viewCell.editorHeight = totalHeight; - this.relayoutCell(); + if (layoutCache) { + this.relayoutCellDebounced(); + } else { + this.relayoutCell(); + } } else { // noop + viewCell.editorHeight = totalHeight; + this.relayoutCell(); this.templateData.outputContainer!.style.display = 'none'; } } @@ -390,12 +401,21 @@ export class CodeCell extends Disposable { } relayoutCell() { + if (this._timer !== null) { + clearTimeout(this._timer); + } + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); } - @debounce(500) + private _timer: any = null; + relayoutCellDebounced() { - this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); + clearTimeout(this._timer); + this._timer = setTimeout(() => { + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); + this._timer = null; + }, 500); } dispose() { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 976b79ef0f..87292a2289 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -101,6 +101,7 @@ export class StatefullMarkdownCell extends Disposable { } const clientHeight = this.cellContainer.clientHeight; + this.viewCell.totalHeight = totalHeight + 32 + clientHeight; notebookEditor.layoutNotebookCell(viewCell, totalHeight + 32 + clientHeight); this.editor.focus(); } else { @@ -109,6 +110,7 @@ export class StatefullMarkdownCell extends Disposable { // switch from editing mode this.editingContainer!.style.display = 'none'; const clientHeight = templateData.container.clientHeight; + this.viewCell.totalHeight = clientHeight; notebookEditor.layoutNotebookCell(viewCell, clientHeight); } else { // first time, readonly mode @@ -123,6 +125,7 @@ export class StatefullMarkdownCell extends Disposable { this.localDisposables.add(markdownRenderer.onDidUpdateRender(() => { const clientHeight = templateData.container.clientHeight; + this.viewCell.totalHeight = clientHeight; notebookEditor.layoutNotebookCell(viewCell, clientHeight); })); @@ -162,7 +165,8 @@ export class StatefullMarkdownCell extends Disposable { clientHeight = this.cellContainer.clientHeight; } - this.notebookEditor.layoutNotebookCell(this.viewCell, this.editor!.getContentHeight() + 32 + clientHeight); + this.viewCell.totalHeight = this.editor!.getContentHeight() + 32 + clientHeight; + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); })); this.localDisposables.add(this.editor!.onDidContentSizeChange(e => { @@ -176,7 +180,8 @@ export class StatefullMarkdownCell extends Disposable { } ); const clientHeight = this.cellContainer.clientHeight; - this.notebookEditor.layoutNotebookCell(this.viewCell, e.contentHeight + 32 + clientHeight); + this.viewCell.totalHeight = e.contentHeight + 32 + clientHeight; + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); } })); @@ -219,7 +224,8 @@ export class StatefullMarkdownCell extends Disposable { this.cellContainer.appendChild(renderedHTML); this.localDisposables.add(markdownRenderer.onDidUpdateRender(() => { const clientHeight = this.cellContainer.clientHeight; - this.notebookEditor.layoutNotebookCell(this.viewCell, clientHeight); + this.viewCell.totalHeight = clientHeight; + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); })); } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index 49d62635eb..2a438c7a3f 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -204,7 +204,7 @@ export abstract class BaseCellViewModel extends Disposable implements ICellViewM return this._editorViewStates; } - restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null) { + restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null, totalHeight?: number) { this._editorViewStates = editorViewStates; } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index d1c0b60d9b..e8e459beef 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -13,6 +13,7 @@ import { CellEditState, ICellViewModel, CellFindMatch, CodeCellLayoutChangeEvent import { CellKind, ICell, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { BaseCellViewModel } from './baseCellViewModel'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import * as editorCommon from 'vs/editor/common/editorCommon'; export class CodeCellViewModel extends BaseCellViewModel implements ICellViewModel { cellKind: CellKind.Code = CellKind.Code; @@ -135,6 +136,22 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod this._onDidChangeLayout.fire(state); } + restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null, totalHeight?: number) { + super.restoreEditorViewState(editorViewStates); + if (totalHeight !== undefined) { + this._layoutInfo = { + fontInfo: this._layoutInfo.fontInfo, + editorHeight: this._layoutInfo.editorHeight, + editorWidth: this._layoutInfo.editorWidth, + outputContainerOffset: this._layoutInfo.outputContainerOffset, + outputTotalHeight: this._layoutInfo.outputTotalHeight, + totalHeight: totalHeight, + indicatorHeight: this._layoutInfo.indicatorHeight, + bottomToolbarOffset: this._layoutInfo.bottomToolbarOffset + }; + } + } + hasDynamicHeight() { if (this.selfSizeMonitoring) { // if there is an output rendered in the webview, it should always be false @@ -153,7 +170,11 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } getHeight(lineHeight: number) { - return EDITOR_TOOLBAR_HEIGHT + EDITOR_TOP_MARGIN + this.lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + BOTTOM_CELL_TOOLBAR_HEIGHT; + if (this._layoutInfo.totalHeight === 0) { + return EDITOR_TOOLBAR_HEIGHT + EDITOR_TOP_MARGIN + this.lineCount * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + BOTTOM_CELL_TOOLBAR_HEIGHT; + } else { + return this._layoutInfo.totalHeight; + } } save() { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 9dbcc3a2a0..8e19cdd982 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -12,8 +12,9 @@ import { ICellViewModel, CellFindMatch, MarkdownCellLayoutInfo, MarkdownCellLayo import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; import { CellKind, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CELL_MARGIN, CELL_RUN_GUTTER, BOTTOM_CELL_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import * as editorCommon from 'vs/editor/common/editorCommon'; export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel { cellKind: CellKind.Markdown = CellKind.Markdown; @@ -28,6 +29,14 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie return this._layoutInfo; } + set totalHeight(newHeight: number) { + this.layoutChange({ totalHeight: newHeight }); + } + + get totalHeight() { + throw new Error('MarkdownCellViewModel.totalHeight is write only'); + } + protected readonly _onDidChangeLayout = new Emitter(); readonly onDidChangeLayout = this._onDidChangeLayout.event; @@ -43,7 +52,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { fontInfo: initialNotebookLayoutInfo?.fontInfo || null, - editorWidth: initialNotebookLayoutInfo?.width || 0 + editorWidth: initialNotebookLayoutInfo?.width || 0, + bottomToolbarOffset: BOTTOM_CELL_TOOLBAR_HEIGHT, + totalHeight: 0 }; this._register(eventDispatcher.onDidChangeLayout((e) => { @@ -59,18 +70,36 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { fontInfo: state.font || null, - editorWidth + editorWidth, + bottomToolbarOffset: BOTTOM_CELL_TOOLBAR_HEIGHT, + totalHeight: state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight }; this._onDidChangeLayout.fire(state); } + restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null, totalHeight?: number) { + super.restoreEditorViewState(editorViewStates); + if (totalHeight !== undefined) { + this._layoutInfo = { + fontInfo: this._layoutInfo.fontInfo, + editorWidth: this._layoutInfo.editorWidth, + bottomToolbarOffset: this._layoutInfo.bottomToolbarOffset, + totalHeight: totalHeight + }; + } + } + hasDynamicHeight() { return true; } getHeight(lineHeight: number) { - return 100; + if (this._layoutInfo.totalHeight === 0) { + return 100; + } else { + return this._layoutInfo.totalHeight; + } } setText(strs: string[]) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 61491846e6..5da6e13232 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -26,6 +26,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; export interface INotebookEditorViewState { editingCells: { [key: number]: boolean }; editorViewStates: { [key: number]: editorCommon.ICodeEditorViewState | null }; + cellTotalHeights?: { [key: number]: number }; scrollPosition?: { left: number; top: number; }; } @@ -272,12 +273,13 @@ export class NotebookViewModel extends Disposable { return; } - this._viewCells.forEach(cell => { + this._viewCells.forEach((cell, index) => { const isEditing = viewState.editingCells && viewState.editingCells[cell.handle]; const editorViewState = viewState.editorViewStates && viewState.editorViewStates[cell.handle]; cell.editState = isEditing ? CellEditState.Editing : CellEditState.Preview; - cell.restoreEditorViewState(editorViewState); + const cellHeight = viewState.cellTotalHeights ? viewState.cellTotalHeights[index] : undefined; + cell.restoreEditorViewState(editorViewState, cellHeight); }); } diff --git a/src/vs/workbench/contrib/notebook/electron-browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/electron-browser/notebook.contribution.ts new file mode 100644 index 0000000000..2a60124bc1 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/electron-browser/notebook.contribution.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { isMacintosh } from 'vs/base/common/platform'; +import { registerAction2 } from 'vs/platform/actions/common/actions'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import * as webviewCommands from 'vs/workbench/contrib/webview/electron-browser/webviewCommands'; +import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { ElectronWebviewBasedWebview } from 'vs/workbench/contrib/webview/electron-browser/webviewElement'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { getActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions'; + +function getActiveElectronBasedWebviewDelegate(accessor: ServicesAccessor): ElectronWebviewBasedWebview | undefined { + + const editorService = accessor.get(IEditorService); + const editor = getActiveNotebookEditor(editorService); + + const webview = editor?.getInnerWebview(); + + if (webview && webview instanceof ElectronWebviewBasedWebview) { + return webview; + } + + return undefined; // {{SQL CARBON EDIT}} struct-null-checks +} + +function registerNotebookCommands(editorId: string): void { + const contextKeyExpr = ContextKeyExpr.and(ContextKeyExpr.equals('activeEditor', editorId), ContextKeyExpr.not('editorFocus') /* https://github.com/Microsoft/vscode/issues/58668 */)!; + + // These commands are only needed on MacOS where we have to disable the menu bar commands + if (isMacintosh) { + registerAction2(class extends webviewCommands.CopyWebviewEditorCommand { constructor() { super(contextKeyExpr, getActiveElectronBasedWebviewDelegate); } }); + registerAction2(class extends webviewCommands.PasteWebviewEditorCommand { constructor() { super(contextKeyExpr, getActiveElectronBasedWebviewDelegate); } }); + registerAction2(class extends webviewCommands.CutWebviewEditorCommand { constructor() { super(contextKeyExpr, getActiveElectronBasedWebviewDelegate); } }); + registerAction2(class extends webviewCommands.UndoWebviewEditorCommand { constructor() { super(contextKeyExpr, getActiveElectronBasedWebviewDelegate); } }); + registerAction2(class extends webviewCommands.RedoWebviewEditorCommand { constructor() { super(contextKeyExpr, getActiveElectronBasedWebviewDelegate); } }); + } +} + +registerNotebookCommands(NotebookEditor.ID); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index bf25b9a820..0e6dc665e7 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -20,6 +20,7 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; export class TestCell implements ICell { uri: URI; @@ -80,6 +81,9 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + getInnerWebview(): Webview | undefined { + throw new Error('Method not implemented.'); + } cancelNotebookCellExecution(cell: ICellViewModel): void { throw new Error('Method not implemented.'); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 64e3154deb..ddb24a09b6 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -51,7 +51,6 @@ import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; class RequestState { @@ -177,13 +176,6 @@ class OutlineViewState { private readonly _onDidChange = new Emitter<{ followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }>(); readonly onDidChange = this._onDidChange.event; - constructor( - @IStorageService private readonly _storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncService: IStorageKeysSyncRegistryService - ) { - storageKeysSyncService.registerStorageKey({ key: 'outline/state', version: 1 }); - } - set followCursor(value: boolean) { if (value !== this._followCursor) { this._followCursor = value; @@ -217,16 +209,16 @@ class OutlineViewState { return this._sortBy; } - persist(): void { - this._storageService.store('outline/state', JSON.stringify({ + persist(storageService: IStorageService): void { + storageService.store('outline/state', JSON.stringify({ followCursor: this.followCursor, sortBy: this.sortBy, filterOnType: this.filterOnType, }), StorageScope.WORKSPACE); } - restore(): void { - let raw = this._storageService.get('outline/state', StorageScope.WORKSPACE); + restore(storageService: IStorageService): void { + let raw = storageService.get('outline/state', StorageScope.WORKSPACE); if (!raw) { return; } @@ -249,7 +241,7 @@ export class OutlinePane extends ViewPane { private _disposables = new Array(); private _editorDisposables = new DisposableStore(); - private _outlineViewState: OutlineViewState; + private _outlineViewState = new OutlineViewState(); private _requestOracle?: RequestOracle; private _domNode!: HTMLElement; private _message!: HTMLDivElement; @@ -270,6 +262,7 @@ export class OutlinePane extends ViewPane { @IInstantiationService private readonly _instantiationService: IInstantiationService, @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IThemeService private readonly _themeService: IThemeService, + @IStorageService private readonly _storageService: IStorageService, @ICodeEditorService private readonly _editorService: ICodeEditorService, @IMarkerDecorationsService private readonly _markerDecorationService: IMarkerDecorationsService, @IConfigurationService private readonly _configurationService: IConfigurationService, @@ -281,7 +274,7 @@ export class OutlinePane extends ViewPane { @ITelemetryService telemetryService: ITelemetryService, ) { super(options, keybindingService, contextMenuService, _configurationService, contextKeyService, viewDescriptorService, _instantiationService, openerService, themeService, telemetryService); - this._outlineViewState = this.instantiationService.createInstance(OutlineViewState); + this._outlineViewState.restore(this._storageService); this._contextKeyFocused = OutlineViewFocused.bindTo(contextKeyService); this._contextKeyFiltered = OutlineViewFiltered.bindTo(contextKeyService); this._disposables.push(this.onDidFocus(_ => this._contextKeyFocused.set(true))); @@ -441,7 +434,7 @@ export class OutlinePane extends ViewPane { } private _onDidChangeUserState(e: { followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }) { - this._outlineViewState.persist(); + this._outlineViewState.persist(this._storageService); if (e.followCursor) { // todo@joh update immediately } diff --git a/src/vs/workbench/contrib/output/browser/media/output.css b/src/vs/workbench/contrib/output/browser/media/output.css new file mode 100644 index 0000000000..3c95882b6c --- /dev/null +++ b/src/vs/workbench/contrib/output/browser/media/output.css @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench .part > .title > .title-actions .switch-output { + display: flex; + align-items: center; + font-size: 11px; + margin-right: 0.3em; + height: 20px; + flex-shrink: 1; + margin-top: 7px; +} + +.monaco-workbench.mac .part > .title > .title-actions .switch-output { + border-radius: 4px; +} + +.monaco-workbench .part > .title > .title-actions .switch-output > .monaco-select-box { + border: none !important; + display: block !important; + background-color: unset !important; +} + +.monaco-pane-view .pane > .pane-header .monaco-action-bar .switch-output.action-item.select-container { + border: none !important; +} + +.monaco-workbench .part > .title > .title-actions .switch-output > .monaco-select-box { + padding: 0 22px 0 6px; +} diff --git a/src/vs/workbench/contrib/output/browser/output.contribution.ts b/src/vs/workbench/contrib/output/browser/output.contribution.ts index c377c26ee1..fa3158bc6e 100644 --- a/src/vs/workbench/contrib/output/browser/output.contribution.ts +++ b/src/vs/workbench/contrib/output/browser/output.contribution.ts @@ -5,6 +5,7 @@ import * as nls from 'vs/nls'; import * as aria from 'vs/base/browser/ui/aria/aria'; +import 'vs/css!./media/output'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -20,7 +21,7 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWo import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { ViewContainer, IViewContainersRegistry, ViewContainerLocation, Extensions as ViewContainerExtensions, IViewsRegistry, IViewsService } from 'vs/workbench/common/views'; +import { ViewContainer, IViewContainersRegistry, ViewContainerLocation, Extensions as ViewContainerExtensions, IViewsRegistry, IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -28,10 +29,9 @@ import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/commo import { IOutputChannelDescriptor, IFileOutputChannelDescriptor } from 'vs/workbench/services/output/common/output'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { assertIsDefined } from 'vs/base/common/types'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; // Register Service registerSingleton(IOutputService, OutputService); @@ -228,11 +228,13 @@ registerAction2(class extends Action2 { }); } async run(accessor: ServicesAccessor): Promise { - const panelService = accessor.get(IPanelService); + const viewsService = accessor.get(IViewsService); + const viewDescriptorService = accessor.get(IViewDescriptorService); + const contextKeyService = accessor.get(IContextKeyService); const layoutService = accessor.get(IWorkbenchLayoutService); - return new class ToggleOutputAction extends TogglePanelAction { + return new class ToggleOutputAction extends ToggleViewAction { constructor() { - super(toggleOutputAcitonId, 'Toggle Output', OUTPUT_VIEW_ID, panelService, layoutService); + super(toggleOutputAcitonId, 'Toggle Output', OUTPUT_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); } }().run(); } diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 22d696956e..fbfadaa7a6 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -31,11 +31,11 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IOutputChannelDescriptor, IOutputChannelRegistry, Extensions } from 'vs/workbench/services/output/common/output'; import { Registry } from 'vs/platform/registry/common/platform'; -import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; +import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox'; import { groupBy } from 'vs/base/common/arrays'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; -import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; +import { editorBackground, selectBorder } from 'vs/platform/theme/common/colorRegistry'; import { addClass } from 'vs/base/browser/dom'; export class OutputViewPane extends ViewPane { @@ -43,7 +43,6 @@ export class OutputViewPane extends ViewPane { private readonly editor: OutputEditor; private channelId: string | undefined; private editorPromise: Promise | null = null; - private actions: IAction[] | undefined; private readonly scrollLockContextKey: IContextKey; get scrollLock(): boolean { return !!this.scrollLockContextKey.get(); } @@ -109,7 +108,7 @@ export class OutputViewPane extends ViewPane { } const model = codeEditor.getModel(); - if (model && this.actions) { + if (model) { const newPositionLine = e.position.lineNumber; const lastLine = model.getLineCount(); this.scrollLock = lastLine !== newPositionLine; @@ -276,7 +275,7 @@ class SwitchOutputActionViewItem extends SelectActionViewItem { constructor( action: IAction, @IOutputService private readonly outputService: IOutputService, - @IThemeService themeService: IThemeService, + @IThemeService private readonly themeService: IThemeService, @IContextViewService contextViewService: IContextViewService ) { super(null, action, [], 0, contextViewService, { ariaLabel: nls.localize('outputChannels', 'Output Channels.') }); @@ -290,6 +289,14 @@ class SwitchOutputActionViewItem extends SelectActionViewItem { this.updateOtions(); } + render(container: HTMLElement): void { + super.render(container); + addClass(container, 'switch-output'); + this._register(attachStylerCallback(this.themeService, { selectBorder }, colors => { + container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : ''; + })); + } + protected getActionContext(option: string, index: number): string { const channel = index < this.outputChannels.length ? this.outputChannels[index] : this.logChannels[index - this.outputChannels.length - 1]; return channel ? channel.id : option; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 60fde8f03e..c3eed31b10 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -341,7 +341,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre protected createSyncIgnoredElement(container: HTMLElement): HTMLElement { const syncIgnoredElement = DOM.append(container, $('span.setting-item-ignored')); const syncIgnoredLabel = new CodiconLabel(syncIgnoredElement); - syncIgnoredLabel.text = `($(eye-closed) ${localize('extensionSyncIgnoredLabel', 'Sync: Ignored')})`; + syncIgnoredLabel.text = `($(sync-ignored) ${localize('extensionSyncIgnoredLabel', 'Sync: Ignored')})`; return syncIgnoredElement; } diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index 4146929147..23e2d57b9c 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -60,7 +60,13 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce @INotificationService notificationService: INotificationService, @IConfigurationService private readonly configurationService: IConfigurationService ) { - super({ showAlias: !Language.isDefaultVariant() }, instantiationService, keybindingService, commandService, telemetryService, notificationService); + super({ + showAlias: !Language.isDefaultVariant(), + noResultsPick: { + label: localize('noCommandResults', "No matching commands"), + commandId: '' + } + }, instantiationService, keybindingService, commandService, telemetryService, notificationService); } private get configuration() { diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index cc9b7a0704..734e91825e 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -8,10 +8,10 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IQuickPickSeparator, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { IViewDescriptorService, IViewsService, ViewContainer, IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry } from 'vs/workbench/common/views'; +import { IViewDescriptorService, IViewsService, ViewContainer, Extensions as ViewExtensions, IViewContainersRegistry } from 'vs/workbench/common/views'; import { IOutputService } from 'vs/workbench/contrib/output/common/output'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { matchesFuzzy } from 'vs/base/common/filters'; @@ -37,7 +37,12 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider { @@ -91,13 +96,12 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider = []; const getViewEntriesForViewlet = (viewlet: ViewletDescriptor, viewContainer: ViewContainer): IViewQuickPickItem[] => { - const views = Registry.as(ViewExtensions.ViewsRegistry).getViews(viewContainer); + const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer); const result: IViewQuickPickItem[] = []; - for (const view of views) { + for (const view of viewDescriptors.allViewDescriptors) { if (this.contextKeyService.contextMatchesRules(view.when)) { result.push({ label: view.name, - ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", view.name), containerLabel: viewlet.name, accept: () => this.viewsService.openView(view.id, true) }); @@ -110,10 +114,9 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider this.viewletService.openViewlet(viewlet.id, true) }); @@ -123,12 +126,13 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider this.panelService.openPanel(panel.id, true) - }); + if (this.includeViewContainer(panel)) { + viewEntries.push({ + label: panel.name, + containerLabel: localize('panels', "Panel"), + accept: () => this.panelService.openPanel(panel.id, true) + }); + } } // Viewlet Views @@ -145,7 +149,6 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider { await this.terminalService.showPanel(true); @@ -162,20 +165,16 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider this.outputService.showChannel(channel.id) }); } - // Add generic ARIA label - viewEntries.forEach(entry => entry.ariaLabel = localize('entryAriaLabel', "{0}, view picker", entry.label)); - return viewEntries; } - private includeViewlet(viewlet: ViewletDescriptor): boolean { - const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).get(viewlet.id); + private includeViewContainer(container: ViewletDescriptor | IPanelIdentifier): boolean { + const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).get(container.id); if (viewContainer?.hideIfEmpty) { return this.viewDescriptorService.getViewDescriptors(viewContainer).activeViewDescriptors.length > 0; } diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts index 30bf78e370..f6296d7593 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts @@ -151,10 +151,7 @@ interface ResourceTemplate { class RepositoryPaneActionRunner extends ActionRunner { - constructor( - private getSelectedResources: () => (ISCMResource | IResourceNode)[], - private focus: () => void - ) { + constructor(private getSelectedResources: () => (ISCMResource | IResourceNode)[]) { super(); } @@ -168,7 +165,6 @@ class RepositoryPaneActionRunner extends ActionRunner { const actualContext = contextIsSelected ? selection : [context]; const args = flatten(actualContext.map(e => ResourceTree.isResourceNode(e) ? ResourceTree.collect(e) : [e])); await action.run(...args); - this.focus(); } } @@ -181,8 +177,7 @@ class ResourceRenderer implements ICompressibleTreeRenderer ViewModel, private labels: ResourceLabels, private actionViewItemProvider: IActionViewItemProvider, - private getSelectedResources: () => (ISCMResource | IResourceNode)[], - private focus: () => void, + private actionRunner: ActionRunner, private themeService: IThemeService, private menus: SCMMenus ) { } @@ -194,7 +189,7 @@ class ResourceRenderer implements ICompressibleTreeRenderer this.getSelectedResources()); + this._register(actionRunner); + this._register(actionRunner.onDidRun(() => { + if (this.repository.input.visible && this.inputEditor.hasWidgetFocus()) { + return; + } + + this.tree.domFocus(); + })); + const renderers = [ new ResourceGroupRenderer(actionViewItemProvider, this.themeService, this.menus), - new ResourceRenderer(() => this.viewModel, this.listLabels, actionViewItemProvider, () => this.getSelectedResources(), () => this.tree.domFocus(), this.themeService, this.menus) + new ResourceRenderer(() => this.viewModel, this.listLabels, actionViewItemProvider, actionRunner, this.themeService, this.menus) ]; const filter = new SCMTreeFilter(); @@ -1032,11 +1037,14 @@ export class RepositoryPane extends ViewPane { actions = this.menus.getResourceContextActions(element); } + const actionRunner = new RepositoryPaneActionRunner(() => this.getSelectedResources()); + actionRunner.onDidRun(() => this.tree.domFocus()); + this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, getActions: () => actions, getActionsContext: () => element, - actionRunner: new RepositoryPaneActionRunner(() => this.getSelectedResources(), () => this.tree.domFocus()) + actionRunner }); } diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index ef8ac90114..3c5788ff66 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/anythingQuickAccess'; -import { IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick, IQuickPickItemWithResource } from 'vs/platform/quickinput/common/quickInput'; import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction, FastAndSlowPicks, Picks, PicksWithActive } from 'vs/platform/quickinput/browser/pickerQuickAccess'; -import { prepareQuery, IPreparedQuery, compareItemsByScore, scoreItem, ScorerCache } from 'vs/base/common/fuzzyScorer'; +import { prepareQuery, IPreparedQuery, compareItemsByFuzzyScore, scoreItemFuzzy, FuzzyScorerCache } from 'vs/base/common/fuzzyScorer'; import { IFileQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { getOutOfWorkspaceEditorResources, extractRangeFromFilter, IWorkbenchSearchConfiguration } from 'vs/workbench/contrib/search/common/search'; @@ -50,9 +50,7 @@ import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { withNullAsUndefined } from 'vs/base/common/types'; import { stripCodicons } from 'vs/base/common/codicons'; -interface IAnythingQuickPickItem extends IPickerQuickAccessItem { - resource: URI | undefined; -} +interface IAnythingQuickPickItem extends IPickerQuickAccessItem, IQuickPickItemWithResource { } interface IEditorSymbolAnythingQuickPickItem extends IAnythingQuickPickItem { resource: URI; @@ -83,7 +81,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider | Promise> | FastAndSlowPicks | null { + private doGetPicks(filter: string, options: { enableEditorSymbolSearch: boolean }, disposables: DisposableStore, token: CancellationToken): Picks | Promise> | FastAndSlowPicks { const query = prepareQuery(filter); // Return early if we have editor symbol picks. We support this by: // - having a previously active global pick (e.g. a file) // - the user typing `@` to start the local symbol query - const editorSymbolPicks = this.getEditorSymbolPicks(query, disposables, token); - if (editorSymbolPicks) { - return editorSymbolPicks; + if (options.enableEditorSymbolSearch) { + const editorSymbolPicks = this.getEditorSymbolPicks(query, disposables, token); + if (editorSymbolPicks) { + return editorSymbolPicks; + } } // If we have a known last active editor symbol pick, we try to restore @@ -361,7 +375,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider compareItemsByScore(anyPickA, anyPickB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache), + (anyPickA, anyPickB) => compareItemsByFuzzyScore(anyPickA, anyPickB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache), AnythingQuickAccessProvider.MAX_RESULTS ); @@ -376,7 +390,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider compareItemsByScore(editorA, editorB, query, false, editorHistoryScorerAccessor, this.pickState.scorerCache)); + return editorHistoryPicks.sort((editorA, editorB) => compareItemsByFuzzyScore(editorA, editorB, query, false, editorHistoryScorerAccessor, this.pickState.scorerCache)); } //#endregion @@ -716,7 +730,8 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider> | null { - const filter = query.original.split(GotoSymbolQuickAccessProvider.PREFIX)[1]?.trim(); + const filterSegments = query.original.split(GotoSymbolQuickAccessProvider.PREFIX); + const filter = filterSegments.length > 1 ? filterSegments[filterSegments.length - 1].trim() : undefined; if (typeof filter !== 'string') { return null; // we need to be searched for editor symbols via `@` } @@ -731,6 +746,12 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index a14873e557..80ba392309 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -5,7 +5,6 @@ import { localize } from 'vs/nls'; import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; -import { fuzzyScore, createMatches, FuzzyScore } from 'vs/base/common/filters'; import { CancellationToken } from 'vs/base/common/cancellation'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -18,20 +17,16 @@ import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/ import { Range } from 'vs/editor/common/core/range'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; -import { IKeyMods } from 'vs/platform/quickinput/common/quickInput'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { createResourceExcludeMatcher } from 'vs/workbench/services/search/common/search'; -import { ResourceMap } from 'vs/base/common/map'; -import { URI } from 'vs/base/common/uri'; +import { IKeyMods, IQuickPickItemWithResource } from 'vs/platform/quickinput/common/quickInput'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { getSelectionSearchString } from 'vs/editor/contrib/find/findController'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { prepareQuery, IPreparedQuery } from 'vs/base/common/fuzzyScorer'; +import { prepareQuery, IPreparedQuery, scoreFuzzy2, pieceToQuery } from 'vs/base/common/fuzzyScorer'; +import { IMatch } from 'vs/base/common/filters'; -interface ISymbolQuickPickItem extends IPickerQuickAccessItem { - resource: URI | undefined; - score: FuzzyScore | undefined; - symbol: IWorkspaceSymbol; +interface ISymbolQuickPickItem extends IPickerQuickAccessItem, IQuickPickItemWithResource { + score?: number; + symbol?: IWorkspaceSymbol; } export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider { @@ -52,8 +47,6 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider(SymbolsQuickAccessProvider.TYPING_SEARCH_DELAY)); - private readonly resourceExcludeMatcher = this._register(createResourceExcludeMatcher(this.instantiationService, this.configurationService)); - get defaultFilterValue(): string | undefined { // Prefer the word under the cursor in the active editor as default filter @@ -70,10 +63,14 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider> { - const workspaceSymbols = await getWorkspaceSymbols(query.original, token); + + // Split between symbol and container query + let symbolQuery: IPreparedQuery; + let containerQuery: IPreparedQuery | undefined; + if (query.values && query.values.length > 1) { + symbolQuery = pieceToQuery(query.values[0]); // symbol: only match on first part + containerQuery = pieceToQuery(query.values.slice(1)); // container: match on all but first parts + } else { + symbolQuery = query; + } + + // Run the workspace symbol query + const workspaceSymbols = await getWorkspaceSymbols(symbolQuery.original, token); if (token.isCancellationRequested) { return []; } const symbolPicks: Array = []; - // Split between symbol and container query - let symbolQuery: IPreparedQuery; - let containerQuery: IPreparedQuery | undefined; - if (query.values && query.values.length > 1) { - symbolQuery = prepareQuery(query.values[0].original); - containerQuery = prepareQuery(query.values[1].original); - } else { - symbolQuery = query; - } - // Convert to symbol picks and apply filtering const openSideBySideDirection = this.configuration.openSideBySideDirection; - const symbolsExcludedByResource = new ResourceMap(); for (const [provider, symbols] of workspaceSymbols) { for (const symbol of symbols) { @@ -130,11 +128,18 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider 0) { + [symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, 0, symbolLabelWithIcon.length - symbolLabel.length /* Readjust matches to account for codicons in label */); + if (!symbolScore) { + continue; + } } const symbolUri = symbol.location.uri; @@ -148,32 +153,23 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider 0) { if (containerLabel) { - containerScore = fuzzyScore(containerQuery.original, containerQuery.originalLowercase, 0, containerLabel, containerLabel.toLowerCase(), 0, true); + [containerScore, containerMatches] = scoreFuzzy2(containerLabel, containerQuery); } if (!containerScore) { continue; } - } - // Filter out symbols that match the global resource filter - if (symbolUri) { - let excludeSymbolByResource = symbolsExcludedByResource.get(symbolUri); - if (typeof excludeSymbolByResource === 'undefined') { - excludeSymbolByResource = this.resourceExcludeMatcher.matches(symbolUri); - symbolsExcludedByResource.set(symbolUri, excludeSymbolByResource); - } - - if (excludeSymbolByResource) { - continue; + if (symbolScore) { + symbolScore += containerScore; // boost symbolScore by containerScore } } - const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`; const deprecated = symbol.tags ? symbol.tags.indexOf(SymbolTag.Deprecated) >= 0 : false; symbolPicks.push({ @@ -181,10 +177,10 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider symbolB.score[0]) { + if (symbolA.score > symbolB.score) { return -1; - } else if (symbolA.score[0] < symbolB.score[0]) { + } + + if (symbolA.score < symbolB.score) { return 1; } } // By name - const symbolAName = symbolA.symbol.name.toLowerCase(); - const symbolBName = symbolB.symbol.name.toLowerCase(); - const res = symbolAName.localeCompare(symbolBName); - if (res !== 0) { - return res; + if (symbolA.symbol && symbolB.symbol) { + const symbolAName = symbolA.symbol.name.toLowerCase(); + const symbolBName = symbolB.symbol.name.toLowerCase(); + const res = symbolAName.localeCompare(symbolBName); + if (res !== 0) { + return res; + } } // By kind - const symbolAKind = SymbolKinds.toCssClassName(symbolA.symbol.kind); - const symbolBKind = SymbolKinds.toCssClassName(symbolB.symbol.kind); - return symbolAKind.localeCompare(symbolBKind); + if (symbolA.symbol && symbolB.symbol) { + const symbolAKind = SymbolKinds.toCssClassName(symbolA.symbol.kind); + const symbolBKind = SymbolKinds.toCssClassName(symbolB.symbol.kind); + return symbolAKind.localeCompare(symbolBKind); + } + + return 0; } } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index d268e6c876..cc7151b92c 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -156,8 +156,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), handler: (accessor: ServicesAccessor) => modifySearchEditorContextLinesCommand(accessor, true), - primary: KeyMod.Alt | KeyCode.KEY_L, - mac: { primary: KeyMod.Alt | KeyCode.US_EQUAL } + primary: KeyMod.Alt | KeyCode.US_EQUAL }); KeybindingsRegistry.registerCommandAndKeybindingRule({ @@ -165,8 +164,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.and(SearchEditorConstants.InSearchEditor), handler: (accessor: ServicesAccessor) => modifySearchEditorContextLinesCommand(accessor, false), - primary: KeyMod.Alt | KeyCode.KEY_L, - mac: { primary: KeyMod.Alt | KeyCode.US_MINUS } + primary: KeyMod.Alt | KeyCode.US_MINUS }); KeybindingsRegistry.registerCommandAndKeybindingRule({ diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index d566d1fa8d..9dcd89d10a 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -240,7 +240,9 @@ export class TaskQuickPick extends Disposable { let taskQuickPickEntries: QuickPickInput[]; if (tasks.length > 0) { taskQuickPickEntries = tasks.map(task => this.createTaskEntry(task)); - taskQuickPickEntries.unshift({ + taskQuickPickEntries.push({ + type: 'separator' + }, { label: nls.localize('TaskQuickPick.goBack', 'Go back ↩'), task: null }); diff --git a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts index 6e9d113411..cd71998874 100644 --- a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts +++ b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts @@ -28,7 +28,11 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider = []; for (const entry of topLevelPicks.entries) { - if (entry.type === 'separator') { - taskPicks.push(entry); - } const highlights = matchesFuzzy(filter, entry.label!, true); if (!highlights) { continue; } + + if (entry.type === 'separator') { + taskPicks.push(entry); + } + const task: Task | ConfiguringTask | string = (entry).task!; const quickAccessEntry: IPickerQuickAccessItem = entry; - quickAccessEntry.ariaLabel = localize('entryAriaLabel', "{0}, tasks picker", entry.label!); quickAccessEntry.highlights = { label: highlights }; quickAccessEntry.trigger = () => { if (ContributedTask.is(task)) { diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index bdde679c7b..29ff609554 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -160,3 +160,32 @@ .monaco-workbench .part.sidebar .title-actions .terminal-action.codicon-split-horizontal { transform: rotate(-90deg); } + +.monaco-workbench .part > .title > .title-actions .switch-terminal { + display: flex; + align-items: center; + font-size: 11px; + margin-right: 0.3em; + height: 20px; + flex-shrink: 1; + margin-top: 7px; +} + +.monaco-workbench.mac .part > .title > .title-actions .switch-terminal { + border-radius: 4px; +} + +.monaco-workbench .part > .title > .title-actions .switch-terminal > .monaco-select-box { + border: none !important; + display: block !important; + background-color: unset !important; +} + +.monaco-pane-view .pane > .pane-header .monaco-action-bar .switch-terminal.action-item.select-container { + border: none !important; +} + +.monaco-workbench .part > .title > .title-actions .switch-terminal > .monaco-select-box { + padding: 0 22px 0 6px; +} + diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index af94ca3f8f..89c38a6f5b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -9,10 +9,8 @@ import { EndOfLinePreference } from 'vs/editor/common/model'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { TERMINAL_VIEW_ID, ITerminalConfigHelper, TitleEventSource, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { TogglePanelAction } from 'vs/workbench/browser/panel'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; +import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IQuickInputService, IPickOptions, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -32,6 +30,11 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { ITerminalInstance, ITerminalService, Direction } from 'vs/workbench/contrib/terminal/browser/terminal'; import { Action2 } from 'vs/platform/actions/common/actions'; import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalsQuickAccess'; +import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; +import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { addClass } from 'vs/base/browser/dom'; +import { selectBorder } from 'vs/platform/theme/common/colorRegistry'; async function getCwdForSplit(configHelper: ITerminalConfigHelper, instance: ITerminalInstance, folders?: IWorkspaceFolder[], commandService?: ICommandService): Promise { switch (configHelper.config.splitCwd) { @@ -60,18 +63,20 @@ async function getCwdForSplit(configHelper: ITerminalConfigHelper, instance: ITe } } -export class ToggleTerminalAction extends TogglePanelAction { +export class ToggleTerminalAction extends ToggleViewAction { public static readonly ID = TERMINAL_COMMAND_ID.TOGGLE; public static readonly LABEL = nls.localize('workbench.action.terminal.toggleTerminal', "Toggle Integrated Terminal"); constructor( id: string, label: string, - @IPanelService panelService: IPanelService, + @IViewsService viewsService: IViewsService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IContextKeyService contextKeyService: IContextKeyService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @ITerminalService private readonly terminalService: ITerminalService ) { - super(id, label, TERMINAL_VIEW_ID, panelService, layoutService); + super(id, label, TERMINAL_VIEW_ID, viewsService, viewDescriptorService, contextKeyService, layoutService); } public run(event?: any): Promise { @@ -717,7 +722,7 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem { constructor( action: IAction, @ITerminalService private readonly terminalService: ITerminalService, - @IThemeService themeService: IThemeService, + @IThemeService private readonly themeService: IThemeService, @IContextViewService contextViewService: IContextViewService ) { super(null, action, terminalService.getTabLabels().map(label => { text: label }), terminalService.activeTabIndex, contextViewService, { ariaLabel: nls.localize('terminals', 'Open Terminals.') }); @@ -729,6 +734,14 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem { this._register(attachSelectBoxStyler(this.selectBox, themeService)); } + render(container: HTMLElement): void { + super.render(container); + addClass(container, 'switch-terminal'); + this._register(attachStylerCallback(this.themeService, { selectBorder }, colors => { + container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : ''; + })); + } + private _updateItems(): void { const items = this.terminalService.getTabLabels().map(label => { text: label }); items.push({ text: SwitchTerminalActionViewItem.SEPARATOR, isDisabled: true }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts index fa5183856b..872af1b520 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts @@ -244,7 +244,7 @@ export class TerminalLinkHandler extends DisposableStore { const wasHandled = await new Promise(r => { const timeoutId = setTimeout(() => { canceled = true; - this._logService.error('An extension intecepted a terminal link but did not return'); + this._logService.error(`An extension intecepted a terminal link but it timed out after ${TerminalLinkHandler.LINK_INTERCEPT_THRESHOLD / 1000} seconds`); r(false); }, TerminalLinkHandler.LINK_INTERCEPT_THRESHOLD); let canceled = false; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts b/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts index fd2afd5b35..5ddceba88b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts @@ -36,7 +36,6 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider this.commandService.executeCommand('workbench.action.terminal.new') }); diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index a6ad3c5dd8..f3c53e175c 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -762,7 +762,11 @@ export class TimelinePane extends ViewPane { const changed = super.setExpanded(expanded); if (changed && this.isBodyVisible()) { - this.onActiveEditorChanged(); + if (!this.followActiveEditor) { + this.setUriCore(this.uri, true); + } else { + this.onActiveEditorChanged(); + } } return changed; @@ -1102,8 +1106,7 @@ class TimelinePaneCommands extends Disposable { this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({ command: { id: 'timeline.toggleFollowActiveEditor', - title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' }, - // title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"), + title: { value: localize('timeline.toggleFollowActiveEditorCommand.follow', "Automatically Follows the Active Editor"), original: 'Automatically Follows the Active Editor' }, icon: { id: 'codicon/eye' }, category: { value: localize('timeline', "Timeline"), original: 'Timeline' }, }, @@ -1115,8 +1118,7 @@ class TimelinePaneCommands extends Disposable { this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({ command: { id: 'timeline.toggleFollowActiveEditor', - title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' }, - // title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"), + title: { value: localize('timeline.toggleFollowActiveEditorCommand.unfollow', "Not Following Active Editor"), original: 'Not Following Active Editor' }, icon: { id: 'codicon/eye-closed' }, category: { value: localize('timeline', "Timeline"), original: 'Timeline' }, }, diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 628a82ac77..a1aa5a40f9 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -251,7 +251,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo return new Promise((resolve, _) => { const quickPick = this.quickInputService.createQuickPick<{ label: string, session: AuthenticationSession }>(); quickPick.title = localize('chooseAccountTitle', "Preferences Sync: Choose Account"); - quickPick.placeholder = localize('chooseAccount', "Choose an account you would like to use for settings sync"); + quickPick.placeholder = localize('chooseAccount', "Choose an account you would like to use for preferences sync"); const dedupedSessions = distinct(sessions, (session) => session.accountName); quickPick.items = dedupedSessions.map(session => { return { @@ -287,10 +287,16 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo if (this.activeAccount) { if (event.removed.length) { const activeWasRemoved = !!event.removed.find(removed => removed === this.activeAccount!.id); - // If the current account was removed, offer to turn off sync if (activeWasRemoved) { - await this.turnOff(); this.setActiveAccount(undefined); + this.notificationService.notify({ + severity: Severity.Info, + message: localize('turned off on logout', "Sync has stopped because you are no longer signed in."), + actions: { + primary: [new Action('turn on sync', localize('turn on sync', "Turn on Sync"), undefined, true, () => this.turnOn())] + } + }); + return; return; } } @@ -683,7 +689,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo } await this.handleFirstTimeSync(); this.userDataSyncEnablementService.setEnablement(true); - this.notificationService.info(localize('sync turned on', "Sync will happen automatically from now on.")); + this.notificationService.info(localize('sync turned on', "Preferences sync is turned on")); this.storageService.store('sync.donotAskPreviewConfirmation', true, StorageScope.GLOBAL); } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts index db815c5fe6..b4f56bdb94 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts @@ -17,7 +17,7 @@ import { URI } from 'vs/base/common/uri'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { FolderThemeIcon } from 'vs/platform/theme/common/themeService'; import { fromNow } from 'vs/base/common/date'; -import { pad } from 'vs/base/common/strings'; +import { pad, uppercaseFirstLetter } from 'vs/base/common/strings'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; export class UserDataSyncViewContribution implements IWorkbenchContribution { @@ -101,7 +101,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { constructor() { super({ id: `workbench.actions.sync.resolveResource`, - title: localize('workbench.actions.sync.resolveResourceRef', "Show full content"), + title: localize('workbench.actions.sync.resolveResourceRef', "Show raw JSON sync data"), menu: { id: MenuId.ViewItemContext, when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /sync-resource-.*/i)) @@ -156,7 +156,7 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider { return ALL_SYNC_RESOURCES.map(resourceKey => ({ handle: resourceKey, collapsibleState: TreeItemCollapsibleState.Collapsed, - label: { label: resourceKey }, + label: { label: uppercaseFirstLetter(resourceKey) }, themeIcon: FolderThemeIcon, })); } diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts index 502f59cda0..cb9719fa93 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInputFactory.ts @@ -16,7 +16,7 @@ interface SerializedIconPath { dark: string | UriComponents; } -interface SerializedWebview { +export interface SerializedWebview { readonly id?: string; readonly viewType: string; readonly title: string; diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewCommands.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewCommands.ts index 4d6eb47862..e12ec1cbf3 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewCommands.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewCommands.ts @@ -42,7 +42,7 @@ export class CopyWebviewEditorCommand extends Action2 { public static readonly ID = 'editor.action.webvieweditor.copy'; public static readonly LABEL = nls.localize('editor.action.webvieweditor.copy', "Copy2"); - constructor(contextKeyExpr: ContextKeyExpression) { + constructor(contextKeyExpr: ContextKeyExpression, readonly getActiveElectronBasedWebviewDelegate: (accessor: ServicesAccessor) => ElectronWebviewBasedWebview | undefined = getActiveElectronBasedWebview) { super({ id: CopyWebviewEditorCommand.ID, title: CopyWebviewEditorCommand.LABEL, @@ -55,7 +55,7 @@ export class CopyWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getActiveElectronBasedWebview(accessor)?.copy(); + this.getActiveElectronBasedWebviewDelegate(accessor)?.copy(); } } @@ -63,7 +63,7 @@ export class PasteWebviewEditorCommand extends Action2 { public static readonly ID = 'editor.action.webvieweditor.paste'; public static readonly LABEL = nls.localize('editor.action.webvieweditor.paste', 'Paste'); - constructor(contextKeyExpr: ContextKeyExpression) { + constructor(contextKeyExpr: ContextKeyExpression, readonly getActiveElectronBasedWebviewDelegate: (accessor: ServicesAccessor) => ElectronWebviewBasedWebview | undefined = getActiveElectronBasedWebview) { super({ id: PasteWebviewEditorCommand.ID, title: PasteWebviewEditorCommand.LABEL, @@ -76,7 +76,7 @@ export class PasteWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getActiveElectronBasedWebview(accessor)?.paste(); + this.getActiveElectronBasedWebviewDelegate(accessor)?.paste(); } } @@ -84,7 +84,7 @@ export class CutWebviewEditorCommand extends Action2 { public static readonly ID = 'editor.action.webvieweditor.cut'; public static readonly LABEL = nls.localize('editor.action.webvieweditor.cut', 'Cut'); - constructor(contextKeyExpr: ContextKeyExpression) { + constructor(contextKeyExpr: ContextKeyExpression, readonly getActiveElectronBasedWebviewDelegate: (accessor: ServicesAccessor) => ElectronWebviewBasedWebview | undefined = getActiveElectronBasedWebview) { super({ id: CutWebviewEditorCommand.ID, title: CutWebviewEditorCommand.LABEL, @@ -97,7 +97,7 @@ export class CutWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getActiveElectronBasedWebview(accessor)?.cut(); + this.getActiveElectronBasedWebviewDelegate(accessor)?.cut(); } } @@ -105,7 +105,7 @@ export class UndoWebviewEditorCommand extends Action2 { public static readonly ID = 'editor.action.webvieweditor.undo'; public static readonly LABEL = nls.localize('editor.action.webvieweditor.undo', "Undo"); - constructor(contextKeyExpr: ContextKeyExpression) { + constructor(contextKeyExpr: ContextKeyExpression, readonly getActiveElectronBasedWebviewDelegate: (accessor: ServicesAccessor) => ElectronWebviewBasedWebview | undefined = getActiveElectronBasedWebview) { super({ id: UndoWebviewEditorCommand.ID, title: UndoWebviewEditorCommand.LABEL, @@ -118,7 +118,7 @@ export class UndoWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getActiveElectronBasedWebview(accessor)?.undo(); + this.getActiveElectronBasedWebviewDelegate(accessor)?.undo(); } } @@ -126,7 +126,7 @@ export class RedoWebviewEditorCommand extends Action2 { public static readonly ID = 'editor.action.webvieweditor.redo'; public static readonly LABEL = nls.localize('editor.action.webvieweditor.redo', "Redo"); - constructor(contextKeyExpr: ContextKeyExpression) { + constructor(contextKeyExpr: ContextKeyExpression, readonly getActiveElectronBasedWebviewDelegate: (accessor: ServicesAccessor) => ElectronWebviewBasedWebview | undefined = getActiveElectronBasedWebview) { super({ id: RedoWebviewEditorCommand.ID, title: RedoWebviewEditorCommand.LABEL, @@ -141,7 +141,7 @@ export class RedoWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getActiveElectronBasedWebview(accessor)?.redo(); + this.getActiveElectronBasedWebviewDelegate(accessor)?.redo(); } } diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts index 5c88dc1943..a63eddc4ea 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts @@ -38,8 +38,17 @@ const viewsWelcomeExtensionPointSchema = Object.freeze { + for (const folderToAdd of foldersToAdd) { const folderURI = folderToAdd.uri; if (this.contains(currentWorkspaceFolderUris, folderURI)) { - return; // already existing + continue; // already existing } try { const result = await this.fileService.resolve(folderURI); if (!result.isDirectory) { - return; + continue; } } catch (e) { /* Ignore */ } storedFoldersToAdd.push(getStoredWorkspaceFolder(folderURI, false, folderToAdd.name, workspaceConfigFolder, slashForPath)); - })); + } // Apply to array of newStoredFolders if (storedFoldersToAdd.length > 0) { diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index d79b3f87a6..8255824bd0 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -74,6 +74,9 @@ export class CodeEditorService extends CodeEditorServiceImpl { if (isCodeEditor(widget)) { return widget; } + if (isCompositeEditor(widget) && isCodeEditor(widget.activeCodeEditor)) { + return widget.activeCodeEditor; + } } return null; diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index 873bb70eba..0c5719be32 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -15,7 +15,7 @@ import * as objects from 'vs/base/common/objects'; import { StopWatch } from 'vs/base/common/stopwatch'; import * as strings from 'vs/base/common/strings'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { compareItemsByScore, IItemAccessor, prepareQuery, ScorerCache } from 'vs/base/common/fuzzyScorer'; +import { compareItemsByFuzzyScore, IItemAccessor, prepareQuery, FuzzyScorerCache } from 'vs/base/common/fuzzyScorer'; import { MAX_FILE_SIZE } from 'vs/base/node/pfs'; import { ICachedSearchStats, IFileQuery, IFileSearchStats, IFolderQuery, IProgressMessage, IRawFileQuery, IRawQuery, IRawTextQuery, ITextQuery, IFileSearchProgressItem, IRawFileMatch, IRawSearchService, ISearchEngine, ISearchEngineSuccess, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ISerializedSearchSuccess, isFilePatternMatch } from 'vs/workbench/services/search/common/search'; import { Engine as FileSearchEngine } from 'vs/workbench/services/search/node/fileSearch'; @@ -179,7 +179,7 @@ export class SearchService implements IRawSearchService { } return allResultsPromise.then(([result, results]) => { - const scorerCache: ScorerCache = cache ? cache.scorerCache : Object.create(null); + const scorerCache: FuzzyScorerCache = cache ? cache.scorerCache : Object.create(null); const sortSW = (typeof config.maxResults !== 'number' || config.maxResults > 0) && StopWatch.create(false); return this.sortResults(config, results, scorerCache, token) .then<[ISerializedSearchSuccess, IRawFileMatch[]]>(sortedResults => { @@ -246,13 +246,13 @@ export class SearchService implements IRawSearchService { return undefined; } - private sortResults(config: IFileQuery, results: IRawFileMatch[], scorerCache: ScorerCache, token?: CancellationToken): Promise { + private sortResults(config: IFileQuery, results: IRawFileMatch[], scorerCache: FuzzyScorerCache, token?: CancellationToken): Promise { // we use the same compare function that is used later when showing the results using fuzzy scoring // this is very important because we are also limiting the number of results by config.maxResults // and as such we want the top items to be included in this result set if the number of items // exceeds config.maxResults. const query = prepareQuery(config.filePattern || ''); - const compare = (matchA: IRawFileMatch, matchB: IRawFileMatch) => compareItemsByScore(matchA, matchB, query, true, FileMatchItemAccessor, scorerCache); + const compare = (matchA: IRawFileMatch, matchB: IRawFileMatch) => compareItemsByFuzzyScore(matchA, matchB, query, true, FileMatchItemAccessor, scorerCache); const maxResults = typeof config.maxResults === 'number' ? config.maxResults : Number.MAX_VALUE; return arrays.topAsync(results, compare, maxResults, 10000, token); @@ -408,7 +408,7 @@ class Cache { resultsToSearchCache: { [searchValue: string]: ICacheRow; } = Object.create(null); - scorerCache: ScorerCache = Object.create(null); + scorerCache: FuzzyScorerCache = Object.create(null); } const FileMatchItemAccessor = new class implements IItemAccessor { diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index f354730cfb..83cf16e209 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -17,6 +17,7 @@ import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/commo import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { IFileService } from 'vs/platform/files/common/files'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; class ResourceModelCollection extends ReferenceCollection> { @@ -26,7 +27,8 @@ class ResourceModelCollection extends ReferenceCollection () => Promise.resolve(p.provideTextContent(resource))); + if (resource.query || resource.fragment) { + type TextModelResolverUri = { + query: boolean; + fragment: boolean; + }; + type TextModelResolverUriMeta = { + query: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + fragment: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + }; + this.telemetryService.publicLog2('textmodelresolveruri', { + query: Boolean(resource.query), + fragment: Boolean(resource.fragment) + }); + } + const model = await first(factories); if (!model) { throw new Error('resource is not available'); diff --git a/src/vs/workbench/services/themes/common/themeExtensionPoints.ts b/src/vs/workbench/services/themes/common/themeExtensionPoints.ts index 5ff351facb..aaec97fd68 100644 --- a/src/vs/workbench/services/themes/common/themeExtensionPoints.ts +++ b/src/vs/workbench/services/themes/common/themeExtensionPoints.ts @@ -147,7 +147,6 @@ export class ThemeRegistry { for (let ext of extensions) { if (this.isProposedApi) { checkProposedApiEnabled(ext.description); - return; } let extensionData: ExtensionData = { extensionId: ext.description.identifier.value, diff --git a/src/vs/workbench/test/browser/api/extHostTypes.test.ts b/src/vs/workbench/test/browser/api/extHostTypes.test.ts index 25097801b6..a85603eddc 100644 --- a/src/vs/workbench/test/browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypes.test.ts @@ -587,6 +587,18 @@ suite('ExtHostTypes', function () { ]); }); + test('SemanticTokensBuilder no modifier', () => { + const builder = new types.SemanticTokensBuilder(); + builder.push(1, 0, 5, 1); + builder.push(1, 10, 4, 2); + builder.push(2, 2, 3, 2); + assert.deepEqual(toArr(builder.build().data), [ + 1, 0, 5, 1, 0, + 0, 10, 4, 2, 0, + 1, 2, 3, 2, 0 + ]); + }); + test('SemanticTokensBuilder out of order 1', () => { const builder = new types.SemanticTokensBuilder(); builder.push(2, 0, 5, 1, 1); diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index a83788d32d..967bbab3a0 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -119,6 +119,9 @@ import 'vs/workbench/contrib/debug/electron-browser/extensionHostDebugService'; // Webview import 'vs/workbench/contrib/webview/electron-browser/webview.contribution'; +// Notebook +import 'vs/workbench/contrib/notebook/electron-browser/notebook.contribution'; + // Extensions Management import 'vs/workbench/contrib/extensions/electron-browser/extensions.contribution'; diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index 5d5c1f5a94..dd45700f01 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -40,8 +40,8 @@ export function setup() { // await app.workbench.debug.openDebugViewlet(); // await app.workbench.debug.waitForTitle(title => /starten/i.test(title)); - await app.workbench.extensions.openExtensionsViewlet(); - await app.workbench.extensions.waitForTitle(title => /extensions/i.test(title)); + // await app.workbench.extensions.openExtensionsViewlet(); + // await app.workbench.extensions.waitForTitle(title => /extensions/i.test(title)); }); }); } diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 8649c9859c..319fb68658 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -2,11 +2,17 @@ # yarn lockfile v1 +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + "@types/glob@*": - version "5.0.33" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.33.tgz#3dff7c6ce09d65abe919c7961dc3dee016f36ad7" - integrity sha512-BcD4yyWz+qmCggaYMSFF0Xn7GkO6tgwm3Fh9Gxk/kQmEU3Z7flQTnVlMyKBUNvXXNTCCyjqK4XT4/2hLd1gQ2A== + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== dependencies: + "@types/events" "*" "@types/minimatch" "*" "@types/node" "*" @@ -16,9 +22,9 @@ integrity sha1-0q4smHTsiCngPwC6pGNbQinOjPE= "@types/minimatch@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.1.tgz#b683eb60be358304ef146f5775db4c0e3696a550" - integrity sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/mkdirp@0.5.1": version "0.5.1" @@ -40,14 +46,14 @@ "@types/node" "*" "@types/node@*": - version "8.0.51" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" - integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== + version "13.11.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" + integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== "@types/node@^12.11.7": - version "12.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a" - integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA== + version "12.12.34" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.34.tgz#0a5d6ae5d22612f0cf5f10320e1fc5d2a745dcb8" + integrity sha512-BneGN0J9ke24lBRn44hVHNeDlrXRYF+VRp0HbSUNnEZahXGAysHZIqnf/hER6aabdBgzM4YOV4jrR8gj4Zfi0g== "@types/rimraf@2.0.2": version "2.0.2" @@ -57,26 +63,11 @@ "@types/glob" "*" "@types/node" "*" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-regex@^0.2.0, ansi-regex@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" - integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" @@ -87,11 +78,6 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-styles@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" - integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -107,19 +93,6 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -149,21 +122,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-filter@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" - integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= - -array-map@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" - integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= - -array-reduce@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" - integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= - array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -184,7 +142,7 @@ async-each@^1.0.0: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== @@ -220,15 +178,22 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -283,18 +248,7 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -chalk@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" - integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= - dependencies: - ansi-styles "^1.1.0" - escape-string-regexp "^1.0.0" - has-ansi "^0.1.0" - strip-ansi "^0.3.0" - supports-color "^0.2.0" - -chalk@^2.0.1: +chalk@^2.0.1, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -324,11 +278,6 @@ chokidar@^1.6.0: optionalDependencies: fsevents "^1.0.0" -chownr@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -348,11 +297,6 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -379,9 +323,9 @@ commander@2.6.0: integrity sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0= commander@^2.8.1: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== component-emitter@^1.2.1: version "1.3.0" @@ -394,33 +338,29 @@ concat-map@0.0.1: integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concurrently@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.1.tgz#ee8b60018bbe86b02df13e5249453c6ececd2521" - integrity sha512-689HrwGw8Rbk1xtV9C4dY6TPJAvIYZbRbnKSAtfJ7tHqICFGoZ0PCWYjxfmerRyxBG0o3sbG3pe7N8vqPwIHuQ== + version "3.6.1" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.6.1.tgz#2f95baec5c4051294dfbb55b57a3b98a3e2b45ec" + integrity sha512-/+ugz+gwFSEfTGUxn0KHkY+19XPRTXR8+7oUK/HxgiN1n7FjeJmkrbSiXAJfyQ0zORgJYPaenmymwon51YXH9Q== dependencies: - chalk "0.5.1" + chalk "^2.4.1" commander "2.6.0" date-fns "^1.23.0" lodash "^4.5.1" + read-pkg "^3.0.0" rx "2.3.24" spawn-command "^0.0.2-1" supports-color "^3.2.3" tree-kill "^1.1.0" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-util-is@~1.0.0: version "1.0.2" @@ -450,11 +390,11 @@ crypt@~0.0.1: integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= date-fns@^1.23.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" - integrity sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw== + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -debug@3.2.6, debug@^3.2.6: +debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -468,13 +408,6 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -485,11 +418,6 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -519,50 +447,40 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" + domelementtype "^2.0.1" + entities "^2.0.0" -domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= +domelementtype@1, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== domhandler@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" - integrity sha1-iS5HAAqZvlW783dP/qBWHYh5wlk= + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== dependencies: domelementtype "1" domutils@^1.5.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" - integrity sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8= + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: dom-serializer "0" domelementtype "1" @@ -577,37 +495,50 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= +entities@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -es-abstract@^1.5.1: - version "1.14.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" - integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: - es-to-primitive "^1.2.0" + is-arrayish "^0.2.1" + +es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + dependencies: + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.0.0" - string.prototype.trimright "^2.0.0" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" is-symbol "^1.0.2" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -618,11 +549,11 @@ esprima@^4.0.0: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== exec-sh@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" - integrity sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg== + version "0.2.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" + integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== dependencies: - merge "^1.1.3" + merge "^1.2.0" expand-brackets@^0.1.4: version "0.1.5" @@ -687,6 +618,11 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -751,45 +687,24 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== - dependencies: - minipass "^2.2.1" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.0.0: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + version "1.2.12" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" + integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -834,10 +749,10 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.5: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== +glob@^7.0.5, glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -846,23 +761,16 @@ glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -graceful-fs@^4.1.11: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -has-ansi@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" - integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= - dependencies: - ansi-regex "^0.2.0" - has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -873,15 +781,10 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-value@^0.3.1: version "0.3.1" @@ -914,7 +817,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -926,31 +829,22 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + htmlparser2@^3.9.2: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg= + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== dependencies: - domelementtype "^1.3.0" + domelementtype "^1.3.1" domhandler "^2.3.0" domutils "^1.5.1" entities "^1.1.1" inherits "^2.0.1" - readable-stream "^2.0.2" - -iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" + readable-stream "^3.1.1" inflight@^1.0.4: version "1.0.6" @@ -960,15 +854,10 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - integrity sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4= +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-accessor-descriptor@^0.1.6: version "0.1.6" @@ -984,6 +873,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -997,14 +891,14 @@ is-buffer@^1.1.5, is-buffer@~1.1.1: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-data-descriptor@^0.1.4: version "0.1.4" @@ -1021,9 +915,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" @@ -1072,13 +966,6 @@ is-extglob@^1.0.0: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -1127,19 +1014,19 @@ is-primitive@^2.0.0: resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.1" is-windows@^1.0.2: version "1.0.2" @@ -1176,10 +1063,10 @@ js-yaml@3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" @@ -1201,9 +1088,19 @@ kind-of@^5.0.0: integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" locate-path@^3.0.0: version "3.0.0" @@ -1213,21 +1110,11 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.16.4: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== - -lodash@^4.17.15: +lodash@^4.16.4, lodash@^4.17.15, lodash@^4.5.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.5.1: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" - integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw== - log-symbols@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -1261,10 +1148,10 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" -merge@^1.1.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" - integrity sha1-dTHjnUlJwoGma4xabgJl6LBYlNo= +merge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" + integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== micromatch@^2.1.5: version "2.3.11" @@ -1311,30 +1198,10 @@ minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== mixin-deep@^1.2.0: version "1.3.2" @@ -1344,17 +1211,17 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= +mkdirp@0.5.4, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" + integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== dependencies: - minimist "0.0.8" + minimist "^1.2.5" mocha-junit-reporter@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz#2e5149ed40fc5d2e3ca71e42db5ab1fec9c6d85c" - integrity sha1-LlFJ7UD8XS48px5C21qx/snG2Fw= + version "1.23.3" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz#941e219dd759ed732f8641e165918aa8b167c981" + integrity sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA== dependencies: debug "^2.2.0" md5 "^2.1.0" @@ -1371,9 +1238,9 @@ mocha-multi-reporters@^1.1.7: lodash "^4.16.4" mocha@^6.1.4: - version "6.2.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" - integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== + version "6.2.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.3.tgz#e648432181d8b99393410212664450a4c1e31912" + integrity sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -1387,7 +1254,7 @@ mocha@^6.1.4: js-yaml "3.13.1" log-symbols "2.2.0" minimatch "3.0.4" - mkdirp "0.5.1" + mkdirp "0.5.4" ms "2.1.1" node-environment-flags "1.0.5" object.assign "4.1.0" @@ -1395,8 +1262,8 @@ mocha@^6.1.4: supports-color "6.0.0" which "1.3.1" wide-align "1.1.3" - yargs "13.3.0" - yargs-parser "13.1.1" + yargs "13.3.2" + yargs-parser "13.1.2" yargs-unparser "1.6.0" ms@2.0.0: @@ -1404,11 +1271,16 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1, ms@^2.1.1: +ms@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -1436,15 +1308,6 @@ ncp@^2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - node-environment-flags@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" @@ -1453,29 +1316,15 @@ node-environment-flags@1.0.5: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.1.1" @@ -1484,39 +1333,6 @@ normalize-path@^2.0.0, normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -1526,10 +1342,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -1543,7 +1359,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0: +object.assign@4.1.0, object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -1554,12 +1370,12 @@ object.assign@4.1.0: object-keys "^1.0.11" object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.omit@^2.0.0: version "2.0.1" @@ -1583,28 +1399,15 @@ once@^1.3.0: dependencies: wrappy "1" -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -1630,6 +1433,14 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -1650,6 +1461,18 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + portastic@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/portastic/-/portastic-1.0.1.tgz#1c9805d43fae8f6a40cf0dbc7794091a2e9d0d2a" @@ -1669,11 +1492,6 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -1688,33 +1506,19 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" readable-stream@^2.0.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readable-stream@^2.0.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -1724,6 +1528,15 @@ readable-stream@^2.0.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.1.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -1783,10 +1596,10 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.7: - version "1.11.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" - integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== +resolve@^1.1.7, resolve@^1.10.0: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" @@ -1796,23 +1609,23 @@ ret@~0.1.10: integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: - glob "^7.0.5" + glob "^7.1.3" rx@2.3.24: version "2.3.24" resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" integrity sha1-FPlQpCF9fjXapxu8vljv9o6ksrc= -safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== +safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== -safe-buffer@^5.1.2: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -1824,27 +1637,12 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@^5.3.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== - -semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -1860,19 +1658,9 @@ set-value@^2.0.0, set-value@^2.0.1: split-string "^3.0.1" shell-quote@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" - integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= - dependencies: - array-filter "~0.0.0" - array-map "~0.0.0" - array-reduce "~0.0.0" - jsonify "~0.0.0" - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== snapdragon-node@^2.0.1: version "2.1.1" @@ -1905,11 +1693,11 @@ snapdragon@^0.8.1: use "^3.1.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" @@ -1930,6 +1718,32 @@ spawn-command@^0.0.2-1: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -1950,15 +1764,6 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - "string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -1976,28 +1781,46 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimleft@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimend@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz#ee497fd29768646d84be2c9b819e292439614373" + integrity sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" -string.prototype.trimright@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimleft@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" + string.prototype.trimstart "^1.0.0" -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== +string.prototype.trimright@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== dependencies: - safe-buffer "~5.1.0" + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimend "^1.0.0" + +string.prototype.trimstart@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz#afe596a7ce9de905496919406c9734845f01a2f2" + integrity sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" @@ -2006,20 +1829,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" - integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= - dependencies: - ansi-regex "^0.2.1" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -2034,7 +1843,12 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@2.0.1, strip-json-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -2053,11 +1867,6 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" -supports-color@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= - supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -2072,19 +1881,6 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -2118,9 +1914,9 @@ to-regex@^3.0.1, to-regex@^3.0.2: safe-regex "^1.1.0" tree-kill@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" - integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== typescript@3.7.5: version "3.7.5" @@ -2155,11 +1951,19 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + watch@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/watch/-/watch-1.0.2.tgz#340a717bde765726fa0aa07d721e0147a551df0c" @@ -2180,7 +1984,7 @@ which@1.3.1: dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -2211,15 +2015,10 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== - -yargs-parser@13.1.1, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -2233,10 +2032,10 @@ yargs-unparser@1.6.0: lodash "^4.17.15" yargs "^13.3.0" -yargs@13.3.0, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== +yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" find-up "^3.0.0" @@ -2247,4 +2046,4 @@ yargs@13.3.0, yargs@^13.3.0: string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.1" + yargs-parser "^13.1.2" diff --git a/yarn.lock b/yarn.lock index 929fdef474..0475aed715 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1290,13 +1290,14 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== +bl@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a" + integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ== dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" block-stream@*: version "0.0.9" @@ -1468,19 +1469,6 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" -buffer-alloc-unsafe@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" - integrity sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo= - -buffer-alloc@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.1.0.tgz#05514d33bf1656d3540c684f65b1202e90eca303" - integrity sha1-BVFNM78WVtNUDGhPZbEgLpDsowM= - dependencies: - buffer-alloc-unsafe "^0.1.0" - buffer-fill "^0.1.0" - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -1491,11 +1479,6 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= -buffer-fill@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-0.1.1.tgz#76d825c4d6e50e06b7a31eb520c04d08cc235071" - integrity sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q== - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1515,6 +1498,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" + integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" @@ -1766,6 +1757,11 @@ chownr@^1.0.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chrome-remote-interface@0.26.1: version "0.26.1" resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.26.1.tgz#6c7d4479742b6d236752d716a9bc2d322d7d8ad2" @@ -2481,6 +2477,13 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + decompress-zip@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/decompress-zip/-/decompress-zip-0.3.0.tgz#ae3bcb7e34c65879adfe77e19c30f86602b4bdb0" @@ -2855,6 +2858,13 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + enhanced-resolve@4.1.0, enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" @@ -4760,6 +4770,11 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= +inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -5505,13 +5520,12 @@ just-debounce@^1.0.0: resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= -keytar@^4.11.0: - version "4.11.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-4.11.0.tgz#891569045b287a0dabe69320e2381e059b02363f" - integrity sha512-cGn2xd4NY0yCBrU5zQ/lwIagP1UBOhUEemi6iSJU2gshN1RHkxHekSdLUji9IWNo5B1Va/iwXXWzGD2p8ziqfQ== +"keytar@github:rmacfarlane/node-keytar#334424bd26414923782f144110f4beda19168d24": + version "5.4.0" + resolved "https://codeload.github.com/rmacfarlane/node-keytar/tar.gz/334424bd26414923782f144110f4beda19168d24" dependencies: nan "2.14.0" - prebuild-install "5.3.0" + prebuild-install "5.3.3" keyv@^3.0.0: version "3.1.0" @@ -6090,6 +6104,11 @@ mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -6174,6 +6193,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz#54c441ce4c96cd7790e10b41a87aa51068ecab2b" + integrity sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g== + mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" @@ -6776,7 +6800,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -7494,10 +7518,10 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0. source-map "^0.6.1" supports-color "^6.1.0" -prebuild-install@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.0.tgz#58b4d8344e03590990931ee088dd5401b03004c8" - integrity sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg== +prebuild-install@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" + integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== dependencies: detect-libc "^1.0.3" expand-template "^2.0.3" @@ -7508,11 +7532,10 @@ prebuild-install@5.3.0: node-abi "^2.7.0" noop-logger "^0.1.1" npmlog "^4.0.1" - os-homedir "^1.0.1" - pump "^2.0.1" + pump "^3.0.0" rc "^1.2.7" - simple-get "^2.7.0" - tar-fs "^1.13.0" + simple-get "^3.0.3" + tar-fs "^2.0.0" tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" @@ -7615,14 +7638,6 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51" @@ -7797,7 +7812,7 @@ read@^1.0.7: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.6, readable-stream@^2.3.3, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -7852,10 +7867,10 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d" - integrity sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw== +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -8516,12 +8531,12 @@ simple-concat@^1.0.0: resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= -simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== dependencies: - decompress-response "^3.3.0" + decompress-response "^4.2.0" once "^1.3.1" simple-concat "^1.0.0" @@ -9112,28 +9127,26 @@ tapable@^1.0.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" integrity sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg== -tar-fs@^1.13.0: - version "1.16.2" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.2.tgz#17e5239747e399f7e77344f5f53365f04af53577" - integrity sha512-LdknWjPEiZC1nOBwhv0JBzfJBGPJar08dZg2rwZe0ZTLQoRGEzgrl7vF3qUEkCHpI/wN9e7RyCuDhMsJUCLPPQ== +tar-fs@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" -tar-stream@^1.1.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" - integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA== +tar-stream@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325" + integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q== dependencies: - bl "^1.0.0" - buffer-alloc "^1.1.0" - end-of-stream "^1.0.0" + bl "^4.0.1" + end-of-stream "^1.4.1" fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.0" - xtend "^4.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" tar@^2.2.1: version "2.2.1" @@ -9290,11 +9303,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-buffer@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9903,10 +9911,10 @@ vsce@1.48.0: yauzl "^2.3.1" yazl "^2.2.2" -vscode-debugprotocol@1.40.0-pre.1: - version "1.40.0-pre.1" - resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.40.0-pre.1.tgz#62c066c0520cc5e318dfc9873907574018bc8460" - integrity sha512-MLlNUSoJbRPNP/7PpnNLOOubZP/X0ObDEjwC6frrn/GR+bT943S1iIdj9aMjT7i93HSpsIAx8YbwkqId7nxLgw== +vscode-debugprotocol@^1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.40.0.tgz#63e1f670a6f5c4928f3f91b27b259a21c4db7861" + integrity sha512-Fwze+9qbLDPuQUhtITJSu/Vk6zIuakNM1iR2ZiZRgRaMEgBpMs2JSKaT0chrhJHCOy6/UbpsUbUBIseF6msV+g== vscode-nls-dev@^3.3.1: version "3.3.1"