Merge remote-tracking branch 'origin/main' into connor4312/cli-wsl-control-2

This commit is contained in:
Connor Peet 2023-01-20 11:32:17 -08:00
commit c600c10579
No known key found for this signature in database
GPG key ID: CF8FD2EA0DBC61BD
349 changed files with 6851 additions and 2613 deletions

View file

@ -4,5 +4,5 @@ contact_links:
url: https://stackoverflow.com/questions/tagged/visual-studio-code
about: Please ask and answer questions here.
- name: Extension Development
url: https://github.com/microsoft/vscode-discussions/discussions/5
url: https://github.com/microsoft/vscode-discussions/discussions
about: Please use this for extension development questions and ideas.

View file

@ -1 +1 @@
2022-08-01T11:24:47.411Z
2023-01-19T08:04:33.652Z

View file

@ -85,6 +85,7 @@ node-pty/lib/*.test.js
node-pty/tools/**
node-pty/deps/**
node-pty/scripts/**
!node-pty/build/Release/spawn-helper
!node-pty/build/Release/*.exe
!node-pty/build/Release/*.dll
!node-pty/build/Release/*.node

View file

@ -56,7 +56,7 @@ steps:
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/sign/${{ target }}/code.exe
rootFolderOrFile: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(ASSET_ID).zip

View file

@ -41,7 +41,7 @@ steps:
- script: |
mkdir -p .build
node build/azure-pipelines/common/computeNodeModulesCacheKey.js x64 > .build/yarnlockhash
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH > .build/yarnlockhash
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
displayName: Prepare yarn cache flags

View file

@ -402,6 +402,10 @@
"name": "vs/workbench/services/search",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/suggest",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/textfile",
"project": "vscode-workbench"

View file

@ -28,6 +28,7 @@ exports.referenceGeneratedDepsByArch = {
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.14)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.2.5)',
'libcairo2 (>= 1.6.0)',
@ -64,6 +65,7 @@ exports.referenceGeneratedDepsByArch = {
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.4)',
'libc6 (>= 2.9)',
@ -84,7 +86,6 @@ exports.referenceGeneratedDepsByArch = {
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 4.1.1)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
@ -126,7 +127,6 @@ exports.referenceGeneratedDepsByArch = {
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 4.1.1)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
@ -142,4 +142,4 @@ exports.referenceGeneratedDepsByArch = {
'xdg-utils (>= 1.0.2)'
]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQjtDQUN4QyxDQUFDO0FBRUYsb0hBQW9IO0FBQ3BILDBDQUEwQztBQUMxQyw4REFBOEQ7QUFDakQsUUFBQSxlQUFlLEdBQUc7SUFDOUIsWUFBWSxDQUFDLHlFQUF5RTtDQUN0RixDQUFDO0FBRVcsUUFBQSw0QkFBNEIsR0FBRztJQUMzQyxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsa0JBQWtCO1FBQ2xCLHNCQUFzQjtRQUN0QixxQkFBcUI7UUFDckIsc0RBQXNEO1FBQ3RELHlCQUF5QjtRQUN6QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLG9CQUFvQjtRQUNwQiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsNEJBQTRCO1FBQzVCLHlCQUF5QjtRQUN6QixVQUFVO1FBQ1YsMEJBQTBCO1FBQzFCLG9CQUFvQjtRQUNwQiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLFVBQVU7UUFDVixZQUFZO1FBQ1osMEJBQTBCO1FBQzFCLGFBQWE7UUFDYixZQUFZO1FBQ1osc0JBQXNCO0tBQ3RCO0lBQ0QsT0FBTyxFQUFFO1FBQ1IsaUJBQWlCO1FBQ2pCLHdCQUF3QjtRQUN4QiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLDJCQUEyQjtRQUMzQixpQkFBaUI7UUFDakIsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixzQkFBc0I7UUFDdEIscUJBQXFCO1FBQ3JCLHNEQUFzRDtRQUN0RCx5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLHNCQUFzQjtRQUN0QixvQkFBb0I7UUFDcEIsMEJBQTBCO1FBQzFCLDBCQUEwQjtRQUMxQix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsdUJBQXVCO1FBQ3ZCLG1CQUFtQjtRQUNuQixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7SUFDRCxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixzQkFBc0I7UUFDdEIscUJBQXFCO1FBQ3JCLHNEQUFzRDtRQUN0RCx3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLHNCQUFzQjtRQUN0QixvQkFBb0I7UUFDcEIsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixvQkFBb0I7UUFDcEIsMEJBQTBCO1FBQzFCLDBCQUEwQjtRQUMxQix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsdUJBQXVCO1FBQ3ZCLG1CQUFtQjtRQUNuQixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7Q0FDRCxDQUFDIn0=
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQjtDQUN4QyxDQUFDO0FBRUYsb0hBQW9IO0FBQ3BILDBDQUEwQztBQUMxQyw4REFBOEQ7QUFDakQsUUFBQSxlQUFlLEdBQUc7SUFDOUIsWUFBWSxDQUFDLHlFQUF5RTtDQUN0RixDQUFDO0FBRVcsUUFBQSw0QkFBNEIsR0FBRztJQUMzQyxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsaUJBQWlCO1FBQ2pCLGtCQUFrQjtRQUNsQixzQkFBc0I7UUFDdEIscUJBQXFCO1FBQ3JCLHNEQUFzRDtRQUN0RCx5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLHNCQUFzQjtRQUN0QixvQkFBb0I7UUFDcEIsMEJBQTBCO1FBQzFCLDBCQUEwQjtRQUMxQix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtJQUNELE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsZ0JBQWdCO1FBQ2hCLHNCQUFzQjtRQUN0QixxQkFBcUI7UUFDckIsc0RBQXNEO1FBQ3RELHlCQUF5QjtRQUN6QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLG9CQUFvQjtRQUNwQiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsNEJBQTRCO1FBQzVCLHlCQUF5QjtRQUN6Qix1QkFBdUI7UUFDdkIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQixVQUFVO1FBQ1YsMEJBQTBCO1FBQzFCLG9CQUFvQjtRQUNwQiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLFVBQVU7UUFDVixZQUFZO1FBQ1osMEJBQTBCO1FBQzFCLGFBQWE7UUFDYixZQUFZO1FBQ1osc0JBQXNCO0tBQ3RCO0lBQ0QsT0FBTyxFQUFFO1FBQ1IsaUJBQWlCO1FBQ2pCLHdCQUF3QjtRQUN4QiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLDJCQUEyQjtRQUMzQixpQkFBaUI7UUFDakIsc0JBQXNCO1FBQ3RCLHFCQUFxQjtRQUNyQixzREFBc0Q7UUFDdEQsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixvQkFBb0I7UUFDcEIsb0JBQW9CO1FBQ3BCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsd0JBQXdCO1FBQ3hCLHFDQUFxQztRQUNyQyx3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLHVCQUF1QjtRQUN2QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7Q0FDRCxDQUFDIn0=

View file

@ -28,6 +28,7 @@ export const referenceGeneratedDepsByArch = {
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.14)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.2.5)',
'libcairo2 (>= 1.6.0)',
@ -64,6 +65,7 @@ export const referenceGeneratedDepsByArch = {
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.4)',
'libc6 (>= 2.9)',
@ -84,7 +86,6 @@ export const referenceGeneratedDepsByArch = {
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 4.1.1)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
@ -126,7 +127,6 @@ export const referenceGeneratedDepsByArch = {
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 4.1.1)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',

4
cli/Cargo.lock generated
View file

@ -134,9 +134,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.11.0"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "byteorder"

View file

@ -247,7 +247,7 @@ impl Platform {
Platform::DarwinARM64 => "server-darwin-arm64",
Platform::WindowsX64 => "server-win32-x64",
Platform::WindowsX86 => "server-win32",
Platform::WindowsARM64 => "server-win32-arm64",
Platform::WindowsARM64 => "server-win32-x64", // we don't publish an arm64 server build yet
}
.to_owned()
}

View file

@ -7,6 +7,7 @@
'use strict';
const path = require('path');
const withBrowserDefaults = require('../shared.webpack.config').browser;
module.exports = withBrowserDefaults({
@ -16,6 +17,11 @@ module.exports = withBrowserDefaults({
},
output: {
filename: 'configurationEditingMain.js'
},
resolve: {
alias: {
'./node/net': path.resolve(__dirname, 'src', 'browser', 'net'),
}
}
});

View file

@ -11,7 +11,12 @@
"icon": "images/icon.png",
"activationEvents": [
"onLanguage:json",
"onLanguage:jsonc"
"onLanguage:jsonc",
"onProfile",
"onProfile:github"
],
"enabledApiProposals": [
"profileContentHandlers"
],
"main": "./out/configurationEditingMain",
"browser": "./dist/browser/configurationEditingMain",
@ -20,7 +25,9 @@
"watch": "gulp watch-extension:configuration-editing"
},
"dependencies": {
"jsonc-parser": "^2.2.1"
"jsonc-parser": "^2.2.1",
"@octokit/rest": "19.0.4",
"tunnel": "^0.0.6"
},
"capabilities": {
"virtualWorkspaces": true,

View file

@ -3,10 +3,4 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Color } from 'vs/base/common/color';
export type styleFn = (colors: { [name: string]: Color | undefined }) => void;
export interface IThemable {
style: styleFn;
}
export const agent = undefined;

View file

@ -7,6 +7,7 @@ import { getLocation, JSONPath, parse, visit, Location } from 'jsonc-parser';
import * as vscode from 'vscode';
import { SettingsDocument } from './settingsDocumentHelper';
import { provideInstalledExtensionProposals } from './extensionsProposals';
import './importExportProfiles';
export function activate(context: vscode.ExtensionContext): void {
//settings.json suggestions

View file

@ -5,10 +5,8 @@
import { Octokit } from '@octokit/rest';
import * as vscode from 'vscode';
import { httpsOverHttp } from 'tunnel';
import { Agent, globalAgent } from 'https';
import { basename } from 'path';
import { URL } from 'url';
import { agent } from './node/net';
class GitHubGistProfileContentHandler implements vscode.ProfileContentHandler {
@ -21,7 +19,6 @@ class GitHubGistProfileContentHandler implements vscode.ProfileContentHandler {
this._octokit = (async () => {
const session = await vscode.authentication.getSession('github', ['gist', 'user:email'], { createIfNone: true });
const token = session.accessToken;
const agent = this.getAgent();
const { Octokit } = await import('@octokit/rest');
@ -35,20 +32,6 @@ class GitHubGistProfileContentHandler implements vscode.ProfileContentHandler {
return this._octokit;
}
private getAgent(url: string | undefined = process.env.HTTPS_PROXY): Agent {
if (!url) {
return globalAgent;
}
try {
const { hostname, port, username, password } = new URL(url);
const auth = username && password && `${username}:${password}`;
return httpsOverHttp({ proxy: { host: hostname, port, proxyAuth: auth } });
} catch (e) {
vscode.window.showErrorMessage(`HTTPS_PROXY environment variable ignored: ${e.message}`);
return globalAgent;
}
}
async saveProfile(name: string, content: string): Promise<{ readonly id: string; readonly link: vscode.Uri } | null> {
const octokit = await this.getOctokit();
const result = await octokit.gists.create({
@ -71,7 +54,7 @@ class GitHubGistProfileContentHandler implements vscode.ProfileContentHandler {
if (!this._public_octokit) {
this._public_octokit = (async () => {
const { Octokit } = await import('@octokit/rest');
return new Octokit({ request: { agent: this.getAgent() }, userAgent: 'GitHub VSCode' });
return new Octokit({ request: { agent }, userAgent: 'GitHub VSCode' });
})();
}
return this._public_octokit;

View file

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Agent, globalAgent } from 'https';
import { URL } from 'url';
import { httpsOverHttp } from 'tunnel';
import { window } from 'vscode';
export const agent = getAgent();
/**
* Return an https agent for the given proxy URL, or return the
* global https agent if the URL was empty or invalid.
*/
function getAgent(url: string | undefined = process.env.HTTPS_PROXY): Agent {
if (!url) {
return globalAgent;
}
try {
const { hostname, port, username, password } = new URL(url);
const auth = username && password && `${username}:${password}`;
return httpsOverHttp({ proxy: { host: hostname, port, proxyAuth: auth } });
} catch (e) {
window.showErrorMessage(`HTTPS_PROXY environment variable ignored: ${e.message}`);
return globalAgent;
}
}

View file

@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'tunnel';

View file

@ -8,6 +8,7 @@
},
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts"
"../../src/vscode-dts/vscode.d.ts",
"../../src/vscode-dts/vscode.proposed.profileContentHandlers.d.ts",
]
}

View file

@ -2,12 +2,187 @@
# yarn lockfile v1
"@octokit/auth-token@^3.0.0":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.2.tgz#a0fc8de149fd15876e1ac78f6525c1c5ab48435f"
integrity sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==
dependencies:
"@octokit/types" "^8.0.0"
"@octokit/core@^4.0.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.1.0.tgz#b6b03a478f1716de92b3f4ec4fd64d05ba5a9251"
integrity sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==
dependencies:
"@octokit/auth-token" "^3.0.0"
"@octokit/graphql" "^5.0.0"
"@octokit/request" "^6.0.0"
"@octokit/request-error" "^3.0.0"
"@octokit/types" "^8.0.0"
before-after-hook "^2.2.0"
universal-user-agent "^6.0.0"
"@octokit/endpoint@^7.0.0":
version "7.0.3"
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.3.tgz#0b96035673a9e3bedf8bab8f7335de424a2147ed"
integrity sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==
dependencies:
"@octokit/types" "^8.0.0"
is-plain-object "^5.0.0"
universal-user-agent "^6.0.0"
"@octokit/graphql@^5.0.0":
version "5.0.4"
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.4.tgz#519dd5c05123868276f3ae4e50ad565ed7dff8c8"
integrity sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==
dependencies:
"@octokit/request" "^6.0.0"
"@octokit/types" "^8.0.0"
universal-user-agent "^6.0.0"
"@octokit/openapi-types@^13.11.0":
version "13.13.1"
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-13.13.1.tgz#a783bacb1817c9f61a2a0c3f81ea22ad62340fdf"
integrity sha512-4EuKSk3N95UBWFau3Bz9b3pheQ8jQYbKmBL5+GSuY8YDPDwu03J4BjI+66yNi8aaX/3h1qDpb0mbBkLdr+cfGQ==
"@octokit/openapi-types@^14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a"
integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==
"@octokit/plugin-paginate-rest@^4.0.0":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.3.1.tgz#553e653ee0318605acd23bf3a799c8bfafdedae3"
integrity sha512-h8KKxESmSFTcXX409CAxlaOYscEDvN2KGQRsLCGT1NSqRW+D6EXLVQ8vuHhFznS9MuH9QYw1GfsUN30bg8hjVA==
dependencies:
"@octokit/types" "^7.5.0"
"@octokit/plugin-request-log@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
"@octokit/plugin-rest-endpoint-methods@^6.0.0":
version "6.7.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz#2f6f17f25b6babbc8b41d2bb0a95a8839672ce7c"
integrity sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==
dependencies:
"@octokit/types" "^8.0.0"
deprecation "^2.3.1"
"@octokit/request-error@^3.0.0":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.2.tgz#f74c0f163d19463b87528efe877216c41d6deb0a"
integrity sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==
dependencies:
"@octokit/types" "^8.0.0"
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request@^6.0.0":
version "6.2.2"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.2.tgz#a2ba5ac22bddd5dcb3f539b618faa05115c5a255"
integrity sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==
dependencies:
"@octokit/endpoint" "^7.0.0"
"@octokit/request-error" "^3.0.0"
"@octokit/types" "^8.0.0"
is-plain-object "^5.0.0"
node-fetch "^2.6.7"
universal-user-agent "^6.0.0"
"@octokit/rest@19.0.4":
version "19.0.4"
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.4.tgz#fd8bed1cefffa486e9ae46a9dc608ce81bcfcbdd"
integrity sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==
dependencies:
"@octokit/core" "^4.0.0"
"@octokit/plugin-paginate-rest" "^4.0.0"
"@octokit/plugin-request-log" "^1.0.4"
"@octokit/plugin-rest-endpoint-methods" "^6.0.0"
"@octokit/types@^7.5.0":
version "7.5.1"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-7.5.1.tgz#4e8b182933c17e1f41cc25d44757dbdb7bd76c1b"
integrity sha512-Zk4OUMLCSpXNI8KZZn47lVLJSsgMyCimsWWQI5hyjZg7hdYm0kjotaIkbG0Pp8SfU2CofMBzonboTqvzn3FrJA==
dependencies:
"@octokit/openapi-types" "^13.11.0"
"@octokit/types@^8.0.0":
version "8.1.1"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.1.1.tgz#92e304e0f00d563667dfdbe0ae6b52e70d5149bb"
integrity sha512-7tjk+6DyhYAmei8FOEwPfGKc0VE1x56CKPJ+eE44zhDbOyMT+9yan8apfQFxo8oEFsy+0O7PiBtH8w0Yo0Y9Kw==
dependencies:
"@octokit/openapi-types" "^14.0.0"
"@types/node@16.x":
version "16.11.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
before-after-hook@^2.2.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==
deprecation@^2.0.0, deprecation@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
jsonc-parser@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
node-fetch@^2.6.7:
version "2.6.8"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.8.tgz#a68d30b162bc1d8fd71a367e81b997e1f4d4937e"
integrity sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==
dependencies:
whatwg-url "^5.0.0"
once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
tunnel@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
universal-user-agent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==

View file

@ -13,7 +13,7 @@ const path = require('path');
module.exports = withDefaults({
context: path.join(__dirname),
entry: {
extension: './src/node/cssServerMain.ts',
extension: './src/node/cssServerNodeMain.ts',
},
output: {
filename: 'cssServerMain.js',

View file

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
import { URI } from 'vscode-uri';
import { promises as fs } from 'fs';
async function setupMain() {
const l10nLog: string[] = [];
const i10lLocation = process.env['VSCODE_L10N_BUNDLE_LOCATION'];
if (i10lLocation) {
try {
// WORKAROUND for https://github.com/microsoft/vscode-l10n/issues/84. DO NOT COPY.
const uri = URI.parse(i10lLocation);
if (uri.scheme === 'file') {
const contents = await (await fs.readFile(uri.fsPath)).toString();
const bundle = JSON.parse(contents).contents.bundle;
l10n.config({ contents: bundle });
} else {
await l10n.config({ uri: i10lLocation });
}
l10nLog.push(`l10n: Configured to ${i10lLocation.toString()}`);
} catch (e) {
l10nLog.push(`l10n: Problems loading ${i10lLocation.toString()} : ${e}`);
}
}
await import('./cssServerMain');
l10nLog.forEach(console.log);
}
setupMain();

View file

@ -8,7 +8,7 @@
"engines": {
"vscode": "0.10.x"
},
"categories": [
"categories": [
"Other"
],
"activationEvents": [
@ -66,6 +66,9 @@
"filenames": [
"git-rebase-todo"
],
"filenamePatterns": [
"**/rebase-merge/done"
],
"configuration": "./languages/git-rebase.language-configuration.json"
},
{

View file

@ -712,6 +712,11 @@
"command": "git.manageUnsafeRepositories",
"title": "%command.manageUnsafeRepositories%",
"category": "Git"
},
{
"command": "git.openRepositoriesInParentFolders",
"title": "%command.openRepositoriesInParentFolders%",
"category": "Git"
}
],
"continueEditSession": [
@ -1162,6 +1167,10 @@
{
"command": "git.manageUnsafeRepositories",
"when": "config.git.enabled && !git.missing && git.unsafeRepositoryCount != 0"
},
{
"command": "git.openRepositoriesInParentFolders",
"when": "config.git.enabled && !git.missing && git.parentRepositoryCount != 0"
}
],
"scm/title": [
@ -2673,6 +2682,41 @@
"tags": [
"experimental"
]
},
"git.openRepositoryInParentFolders": {
"type": "string",
"enum": [
"always",
"never",
"prompt"
],
"enumDescriptions": [
"%config.openRepositoryInParentFolders.always%",
"%config.openRepositoryInParentFolders.never%",
"%config.openRepositoryInParentFolders.prompt%"
],
"default": "prompt",
"markdownDescription": "%config.openRepositoryInParentFolders%",
"scope": "resource"
},
"git.publishBeforeContinueOn": {
"type": "string",
"enum": [
"prompt",
"always",
"never"
],
"markdownEnumDescriptions": [
"%config.publishBeforeContinueOn.prompt%",
"%config.publishBeforeContinueOn.always%",
"%config.publishBeforeContinueOn.never%"
],
"default": "prompt",
"markdownDescription": "%config.publishBeforeContinueOn%",
"scope": "resource",
"tags": [
"experimental"
]
}
}
},
@ -2818,14 +2862,14 @@
{
"view": "scm",
"contents": "%view.workbench.scm.empty%",
"when": "config.git.enabled && !git.missing && workbenchState == empty && git.unsafeRepositoryCount == 0",
"when": "config.git.enabled && !git.missing && workbenchState == empty && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0",
"enablement": "git.state == initialized",
"group": "2_open@1"
},
{
"view": "scm",
"contents": "%view.workbench.scm.emptyWorkspace%",
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount == 0 && git.unsafeRepositoryCount == 0",
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount == 0 && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0",
"enablement": "git.state == initialized",
"group": "2_open@1"
},
@ -2842,15 +2886,25 @@
{
"view": "scm",
"contents": "%view.workbench.scm.folder%",
"when": "config.git.enabled && !git.missing && git.state == initialized && workbenchState == folder && scmRepositoryCount == 0 && git.unsafeRepositoryCount == 0 && remoteName != 'codespaces'",
"when": "config.git.enabled && !git.missing && git.state == initialized && workbenchState == folder && scmRepositoryCount == 0 && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0 && remoteName != 'codespaces'",
"group": "5_scm@1"
},
{
"view": "scm",
"contents": "%view.workbench.scm.workspace%",
"when": "config.git.enabled && !git.missing && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0 && scmRepositoryCount == 0 && git.unsafeRepositoryCount == 0 && remoteName != 'codespaces'",
"when": "config.git.enabled && !git.missing && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0 && scmRepositoryCount == 0 && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0 && remoteName != 'codespaces'",
"group": "5_scm@1"
},
{
"view": "scm",
"contents": "%view.workbench.scm.repositoryInParentFolders%",
"when": "config.git.enabled && !git.missing && git.state == initialized && git.parentRepositoryCount == 1"
},
{
"view": "scm",
"contents": "%view.workbench.scm.repositoriesInParentFolders%",
"when": "config.git.enabled && !git.missing && git.state == initialized && git.parentRepositoryCount > 1"
},
{
"view": "scm",
"contents": "%view.workbench.scm.unsafeRepository%",
@ -2864,15 +2918,13 @@
{
"view": "explorer",
"contents": "%view.workbench.cloneRepository%",
"when": "config.git.enabled",
"enablement": "git.state == initialized",
"when": "config.git.enabled && git.state == initialized && scmRepositoryCount == 0",
"group": "5_scm@1"
},
{
"view": "explorer",
"contents": "%view.workbench.learnMore%",
"when": "config.git.enabled",
"enablement": "git.state == initialized",
"when": "config.git.enabled && git.state == initialized && scmRepositoryCount == 0",
"group": "5_scm@10"
}
]

View file

@ -104,6 +104,7 @@
"command.timelineSelectForCompare": "Select for Compare",
"command.timelineCompareWithSelected": "Compare with Selected",
"command.manageUnsafeRepositories": "Manage Unsafe Repositories",
"command.openRepositoriesInParentFolders": "Open Repositories In Parent Folders",
"command.api.getRepositories": "Get Repositories",
"command.api.getRepositoryState": "Get Repository State",
"command.api.getRemoteSources": "Get Remote Sources",
@ -242,6 +243,14 @@
"config.useIntegratedAskPass": "Controls whether GIT_ASKPASS should be overwritten to use the integrated version.",
"config.mergeEditor": "Open the merge editor for files that are currently under conflict.",
"config.optimisticUpdate": "Controls whether to optimistically update the state of the Source Control view after running git commands.",
"config.openRepositoryInParentFolders": "Control whether a repository in the parent folders of the workspace, open file(s) should be opened.",
"config.openRepositoryInParentFolders.always": "Always open a repository in the parent folders of the workspace, open file(s).",
"config.openRepositoryInParentFolders.never": "Never open a repository in the parent folders of the workspace, open file(s).",
"config.openRepositoryInParentFolders.prompt": "Prompt before opening a repository in the parent folders of the workspace, open file(s).",
"config.publishBeforeContinueOn": "Controls whether to publish unpublished git state when using Continue Working On from a git repository.",
"config.publishBeforeContinueOn.always": "Always publish unpublished git state when using Continue Working On from a git repository",
"config.publishBeforeContinueOn.never": "Never publish unpublished git state when using Continue Working On from a git repository",
"config.publishBeforeContinueOn.prompt": "Prompt to publish unpublished git state when using Continue Working On from a git repository",
"submenu.explorer": "Git",
"submenu.commit": "Commit",
"submenu.commit.amend": "Amend",
@ -333,6 +342,24 @@
"view.workbench.scm.scanWorkspaceForRepositories": {
"message": "Scanning workspace for git repositories..."
},
"view.workbench.scm.repositoryInParentFolders": {
"message": "A git repository was found in one of the parent directories of the workspace, open file(s).\n[Open Repository](command:git.openRepositoriesInParentFolders)\nUse [this setting](command:workbench.action.openSettings?%5B%22git.openRepositoryInParentFolders%22%5D) to control how git repositories in parent directories of the workspace, open file(s) are opened. To learn more [read our docs](https://aka.ms/vscode-git-external-repository).",
"comment": [
"{Locked='](command:git.openRepositoriesInParentFolders'}",
"{Locked='](command:workbench.action.openSettings?%5B%22git.openRepositoryInParentFolders%22%5D'}",
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for VS Code",
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
]
},
"view.workbench.scm.repositoriesInParentFolders": {
"message": "Git repositories were found in one of the parent directories of the workspace, open file(s).\n[Open Repository](command:git.openRepositoriesInParentFolders)\nUse [this setting](command:workbench.action.openSettings?%5B%22git.openRepositoryInParentFolders%22%5D) to control how git repositories in parent directories of the workspace, open file(s) are opened. To learn more [read our docs](https://aka.ms/vscode-git-external-repository).",
"comment": [
"{Locked='](command:git.openRepositoriesInParentFolders'}",
"{Locked='](command:workbench.action.openSettings?%5B%22git.openRepositoryInParentFolders%22%5D'}",
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for VS Code",
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
]
},
"view.workbench.scm.unsafeRepository": {
"message": "The detected git repository is potentially unsafe as the folder is owned by someone other than the current user.\n[Manage Unsafe Repositories](command:git.manageUnsafeRepositories)\nTo learn more about unsafe repositories [read our docs](https://aka.ms/vscode-git-unsafe-repository).",
"comment": [

View file

@ -191,7 +191,7 @@ class FetchAllRemotesItem implements QuickPickItem {
}
}
class UnsafeRepositoryItem implements QuickPickItem {
class RepositoryItem implements QuickPickItem {
get label(): string {
return `$(repo) ${this.path}`;
}
@ -2263,11 +2263,10 @@ export class CommandCenter {
run = force => repository.deleteBranch(name, force);
} else {
const getBranchPicks = async () => {
const refs = await repository.getRefs({ pattern: 'refs/heads/*' });
const refs = await repository.getRefs({ pattern: 'refs/heads' });
const currentHead = repository.HEAD && repository.HEAD.name;
return refs.filter(ref => ref.type === RefType.Head && ref.name !== currentHead)
.map(ref => new BranchDeleteItem(ref));
return refs.filter(ref => ref.name !== currentHead).map(ref => new BranchDeleteItem(ref));
};
const placeHolder = l10n.t('Select a branch to delete');
@ -2425,7 +2424,7 @@ export class CommandCenter {
@command('git.deleteTag', { repository: true })
async deleteTag(repository: Repository): Promise<void> {
const tagPicks = async (): Promise<TagItem[] | QuickPickItem[]> => {
const remoteTags = await repository.getRefs({ pattern: 'refs/tags/*' });
const remoteTags = await repository.getRefs({ pattern: 'refs/tags' });
return remoteTags.length === 0 ? [{ label: l10n.t('$(info) This repository has no tags.') }] : remoteTags.map(ref => new TagItem(ref));
};
@ -3336,6 +3335,38 @@ export class CommandCenter {
repository.closeDiffEditors(undefined, undefined, true);
}
@command('git.openRepositoriesInParentFolders')
async openRepositoriesInParentFolders(): Promise<void> {
const parentRepositories: string[] = [];
const title = l10n.t('Open Repositories In Parent Folders');
const placeHolder = l10n.t('Pick a repository to open');
const allRepositoriesLabel = l10n.t('All Repositories');
const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel };
const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.parentRepositories.keys()).sort().map(r => new RepositoryItem(r));
const items = this.model.parentRepositories.size === 1 ? [...repositoriesQuickPickItems] :
[...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem];
const repositoryItem = await window.showQuickPick(items, { title, placeHolder });
if (!repositoryItem) {
return;
}
if (repositoryItem === allRepositoriesQuickPickItem) {
// All Repositories
parentRepositories.push(...this.model.parentRepositories.keys());
} else {
// One Repository
parentRepositories.push((repositoryItem as RepositoryItem).path);
}
for (const parentRepository of parentRepositories) {
await this.model.openParentRepository(parentRepository);
}
}
@command('git.manageUnsafeRepositories')
async manageUnsafeRepositories(): Promise<void> {
const unsafeRepositories: string[] = [];
@ -3346,13 +3377,13 @@ export class CommandCenter {
const allRepositoriesLabel = l10n.t('All Repositories');
const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel };
const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.unsafeRepositories.keys()).sort().map(r => new UnsafeRepositoryItem(r));
const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.unsafeRepositories.keys()).sort().map(r => new RepositoryItem(r));
quickpick.items = this.model.unsafeRepositories.size === 1 ? [...repositoriesQuickPickItems] :
[...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem];
quickpick.show();
const repositoryItem = await new Promise<UnsafeRepositoryItem | QuickPickItem | undefined>(
const repositoryItem = await new Promise<RepositoryItem | QuickPickItem | undefined>(
resolve => {
quickpick.onDidAccept(() => resolve(quickpick.activeItems[0]));
quickpick.onDidHide(() => resolve(undefined));
@ -3368,7 +3399,7 @@ export class CommandCenter {
unsafeRepositories.push(...this.model.unsafeRepositories.keys());
} else {
// One Repository
unsafeRepositories.push((repositoryItem as UnsafeRepositoryItem).path);
unsafeRepositories.push((repositoryItem as RepositoryItem).path);
}
for (const unsafeRepository of unsafeRepositories) {

View file

@ -5,6 +5,7 @@
import * as path from 'path';
import * as vscode from 'vscode';
import { RefType } from './api/git';
import { Model } from './model';
export class GitEditSessionIdentityProvider implements vscode.EditSessionIdentityProvider, vscode.Disposable {
@ -13,6 +14,13 @@ export class GitEditSessionIdentityProvider implements vscode.EditSessionIdentit
constructor(private model: Model) {
this.providerRegistration = vscode.workspace.registerEditSessionIdentityProvider('file', this);
vscode.workspace.onWillCreateEditSessionIdentity((e) => {
const publishBeforeContinueOn = vscode.workspace.getConfiguration('git').get<'never' | 'always' | 'prompt'>('publishBeforeContinueOn', 'prompt');
if (publishBeforeContinueOn !== 'never') {
e.waitUntil(this._onWillCreateEditSessionIdentity(e.workspaceFolder, e.token, publishBeforeContinueOn));
}
});
}
dispose() {
@ -58,6 +66,53 @@ export class GitEditSessionIdentityProvider implements vscode.EditSessionIdentit
return vscode.EditSessionIdentityMatch.Partial;
}
}
private async _onWillCreateEditSessionIdentity(workspaceFolder: vscode.WorkspaceFolder, cancellationToken: vscode.CancellationToken, publishBeforeContinueOn: 'always' | 'prompt'): Promise<void> {
const cancellationPromise = createCancellationPromise(cancellationToken);
await Promise.race([this._doPublish(workspaceFolder, publishBeforeContinueOn), cancellationPromise]);
}
private async _doPublish(workspaceFolder: vscode.WorkspaceFolder, publishBeforeContinueOn: 'always' | 'prompt') {
await this.model.openRepository(path.dirname(workspaceFolder.uri.fsPath));
const repository = this.model.getRepository(workspaceFolder.uri);
if (!repository) {
return;
}
await repository.status();
// If this branch hasn't been published to the remote yet,
// ensure that it is published before Continue On is invoked
if (!repository.HEAD?.upstream && repository.HEAD?.type === RefType.Head) {
if (publishBeforeContinueOn === 'prompt') {
const always = vscode.l10n.t('Always');
const never = vscode.l10n.t('Never');
const selection = await vscode.window.showInformationMessage(
vscode.l10n.t('The current branch is not published to the remote. Would you like to publish it to access your changes elsewhere?'),
{ modal: true },
...[always, never]
);
switch (selection) {
case always:
vscode.workspace.getConfiguration('git').update('publishBeforeContinueOn', 'always');
break;
case never:
vscode.workspace.getConfiguration('git').update('publishBeforeContinueOn', 'never');
default:
return;
}
}
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: vscode.l10n.t('Publishing branch...')
}, async () => {
await vscode.commands.executeCommand('git.publish');
});
}
}
}
function normalizeEditSessionIdentity(identity: string) {
@ -73,3 +128,14 @@ function normalizeEditSessionIdentity(identity: string) {
sha
};
}
function createCancellationPromise(cancellationToken: vscode.CancellationToken) {
return new Promise((resolve, _) => {
if (cancellationToken.isCancellationRequested) {
resolve(undefined);
}
cancellationToken.onCancellationRequested(() => {
resolve(undefined);
});
});
}

View file

@ -12,7 +12,7 @@ import * as which from 'which';
import { EventEmitter } from 'events';
import * as iconv from '@vscode/iconv-lite-umd';
import * as filetype from 'file-type';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows } from './util';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows, pathEquals } from './util';
import { CancellationError, CancellationToken, ConfigurationChangeEvent, LogOutputChannel, Progress, Uri, workspace } from 'vscode';
import { detectEncoding } from './encoding';
import { Ref, RefType, Branch, Remote, ForcePushMode, GitErrorCodes, LogOptions, Change, Status, CommitOptions, RefQuery } from './api/git';
@ -497,10 +497,14 @@ export class Git {
),
);
if (networkPath !== undefined) {
// If the repository is at the root of the mapped drive then we
// have to append `\` (ex: D:\) otherwise the path is not valid.
const isDriveRoot = pathEquals(repoUri.fsPath, networkPath);
return path.normalize(
repoUri.fsPath.replace(
networkPath,
`${letter.toLowerCase()}:${networkPath.endsWith('\\') ? '\\' : ''}`
`${letter.toLowerCase()}:${isDriveRoot || networkPath.endsWith('\\') ? '\\' : ''}`
),
);
}
@ -2092,7 +2096,7 @@ export class Repository {
HEAD = await this.getBranch(HEAD.name);
} else if (HEAD.commit) {
// Tag || Commit
const tags = await this.getRefs({ pattern: 'refs/tags/*' });
const tags = await this.getRefs({ pattern: 'refs/tags' });
const tag = tags.find(tag => tag.commit === HEAD!.commit);
if (tag) {

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, commands, LogOutputChannel, l10n, ProgressLocation } from 'vscode';
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, commands, LogOutputChannel, l10n, ProgressLocation, WorkspaceFolder } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators';
@ -34,18 +34,13 @@ class RepositoryPick implements QuickPickItem {
constructor(public readonly repository: Repository, public readonly index: number) { }
}
/**
* Key - normalized path used in user interface
* Value - path extracted from the output of the `git status` command
* used when calling `git config --global --add safe.directory`
*/
class UnsafeRepositoryMap extends Map<string, string> {
abstract class RepositoryMap<T = void> extends Map<string, T> {
constructor() {
super();
this.updateContextKey();
}
override set(key: string, value: string): this {
override set(key: string, value: T): this {
const result = super.set(key, value);
this.updateContextKey();
@ -59,11 +54,30 @@ class UnsafeRepositoryMap extends Map<string, string> {
return result;
}
private updateContextKey(): void {
abstract updateContextKey(): void;
}
/**
* Key - normalized path used in user interface
* Value - path extracted from the output of the `git status` command
* used when calling `git config --global --add safe.directory`
*/
class UnsafeRepositoryMap extends RepositoryMap<string> {
updateContextKey(): void {
commands.executeCommand('setContext', 'git.unsafeRepositoryCount', this.size);
}
}
/**
* Key - normalized path used in user interface
* Value - value indicating whether the repository should be opened
*/
class ParentRepositoryMap extends RepositoryMap {
updateContextKey(): void {
commands.executeCommand('setContext', 'git.parentRepositoryCount', this.size);
}
}
export interface ModelChangeEvent {
repository: Repository;
uri: Uri;
@ -138,14 +152,28 @@ export class Model implements IRemoteSourcePublisherRegistry, IPostCommitCommand
private _onDidChangePostCommitCommandsProviders = new EventEmitter<void>();
readonly onDidChangePostCommitCommandsProviders = this._onDidChangePostCommitCommandsProviders.event;
private showRepoOnHomeDriveRootWarning = true;
private pushErrorHandlers = new Set<PushErrorHandler>();
private _unsafeRepositories = new UnsafeRepositoryMap();
get unsafeRepositories(): Map<string, string> {
get unsafeRepositories(): UnsafeRepositoryMap {
return this._unsafeRepositories;
}
private _parentRepositories = new ParentRepositoryMap();
get parentRepositories(): ParentRepositoryMap {
return this._parentRepositories;
}
/**
* We maintain a map containing both the path and the canonical path of the
* workspace folders. We are doing this as `git.exe` expands the symbolic links
* while there are scenarios in which VS Code does not.
*
* Key - path of the workspace folder
* Value - canonical path of the workspace folder
*/
private _workspaceFolders = new Map<string, string>();
private disposables: Disposable[] = [];
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private logger: LogOutputChannel, private telemetryReporter: TelemetryReporter) {
@ -168,7 +196,9 @@ export class Model implements IRemoteSourcePublisherRegistry, IPostCommitCommand
private async doInitialScan(): Promise<void> {
const config = workspace.getConfiguration('git');
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
const parentRepositoryConfig = config.get<'always' | 'never' | 'prompt'>('openRepositoryInParentFolders', 'prompt');
// Initial repository scan function
const initialScanFn = () => Promise.all([
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] }),
this.onDidChangeVisibleTextEditors(window.visibleTextEditors),
@ -181,8 +211,12 @@ export class Model implements IRemoteSourcePublisherRegistry, IPostCommitCommand
await initialScanFn();
}
// Unsafe repositories notification
if (this._unsafeRepositories.size !== 0) {
if (this._parentRepositories.size !== 0 &&
parentRepositoryConfig === 'prompt') {
// Parent repositories notification
this.showParentRepositoryNotification();
} else if (this._unsafeRepositories.size !== 0) {
// Unsafe repositories notification
this.showUnsafeRepositoryNotification();
}
@ -394,65 +428,88 @@ export class Model implements IRemoteSourcePublisherRegistry, IPostCommitCommand
}
try {
const rawRoot = await this.git.getRepositoryRoot(repoPath);
// This can happen whenever `path` has the wrong case sensitivity in
// case insensitive file systems
// https://github.com/microsoft/vscode/issues/33498
const repositoryRoot = Uri.file(rawRoot).fsPath;
this.logger.trace(`Repository root: ${repositoryRoot}`);
const { repositoryRoot, unsafeRepositoryMatch } = await this.getRepositoryRoot(repoPath);
this.logger.trace(`Repository root for path ${repoPath} is: ${repositoryRoot}`);
if (this.getRepositoryExact(repositoryRoot)) {
this.logger.trace(`Repository for path ${repositoryRoot} already exists`);
return;
}
if (this.shouldRepositoryBeIgnored(rawRoot)) {
if (this.shouldRepositoryBeIgnored(repositoryRoot)) {
this.logger.trace(`Repository for path ${repositoryRoot} is ignored`);
return;
}
// On Window, opening a git repository from the root of the HOMEDRIVE poses a security risk.
// We will only a open git repository from the root of the HOMEDRIVE if the user explicitly
// opens the HOMEDRIVE as a folder. Only show the warning once during repository discovery.
if (process.platform === 'win32' && process.env.HOMEDRIVE && pathEquals(`${process.env.HOMEDRIVE}\\`, repositoryRoot)) {
const isRepoInWorkspaceFolders = (workspace.workspaceFolders ?? []).find(f => pathEquals(f.uri.fsPath, repositoryRoot))!!;
// Handle git repositories that are in parent folders
const parentRepositoryConfig = config.get<'always' | 'never' | 'prompt'>('openRepositoryInParentFolders', 'prompt');
if (parentRepositoryConfig !== 'always' && this.globalState.get<boolean>(`parentRepository:${repositoryRoot}`) !== true) {
const isRepositoryOutsideWorkspace = await this.isRepositoryOutsideWorkspace(repositoryRoot);
if (isRepositoryOutsideWorkspace) {
this.logger.trace(`Repository in parent folder: ${repositoryRoot}`);
if (!isRepoInWorkspaceFolders) {
if (this.showRepoOnHomeDriveRootWarning) {
window.showWarningMessage(l10n.t('Unable to automatically open the git repository at "{0}". To open that git repository, open it directly as a folder in VS Code.', repositoryRoot));
this.showRepoOnHomeDriveRootWarning = false;
if (!this._parentRepositories.has(repositoryRoot)) {
// Show a notification if the parent repository is opened after the initial scan
if (this.state === 'initialized' && parentRepositoryConfig === 'prompt') {
this.showParentRepositoryNotification();
}
this._parentRepositories.set(repositoryRoot);
}
this.logger.trace(`Repository for path ${repositoryRoot} is on the root of the HOMEDRIVE`);
return;
}
}
// Handle unsafe repositories
if (unsafeRepositoryMatch && unsafeRepositoryMatch.length === 3) {
this.logger.trace(`Unsafe repository: ${repositoryRoot}`);
// Show a notification if the unsafe repository is opened after the initial scan
if (this._state === 'initialized' && !this._unsafeRepositories.has(repositoryRoot)) {
this.showUnsafeRepositoryNotification();
}
this._unsafeRepositories.set(repositoryRoot, unsafeRepositoryMatch[2]);
return;
}
// Open repository
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
const repository = new Repository(this.git.open(repositoryRoot, dotGit, this.logger), this, this, this, this.globalState, this.logger, this.telemetryReporter);
this.open(repository);
repository.status(); // do not await this, we want SCM to know about the repo asap
} catch (ex) {
} catch (err) {
// noop
this.logger.trace(`Opening repository for path='${repoPath}' failed; ex=${err}`);
}
}
async openParentRepository(repoPath: string): Promise<void> {
// Mark the repository to be opened from the parent folders
this.globalState.update(`parentRepository:${repoPath}`, true);
await this.openRepository(repoPath);
this.parentRepositories.delete(repoPath);
}
private async getRepositoryRoot(repoPath: string): Promise<{ repositoryRoot: string; unsafeRepositoryMatch: RegExpMatchArray | null }> {
try {
const rawRoot = await this.git.getRepositoryRoot(repoPath);
// This can happen whenever `path` has the wrong case sensitivity in case
// insensitive file systems https://github.com/microsoft/vscode/issues/33498
return { repositoryRoot: Uri.file(rawRoot).fsPath, unsafeRepositoryMatch: null };
} catch (err) {
// Handle unsafe repository
const match = /^fatal: detected dubious ownership in repository at \'([^']+)\'[\s\S]*git config --global --add safe\.directory '?([^'\n]+)'?$/m.exec(ex.stderr);
if (match && match.length === 3) {
const unsafeRepositoryPath = path.normalize(match[1]);
this.logger.trace(`Unsafe repository: ${unsafeRepositoryPath}`);
// Show a notification if the unsafe repository is opened after the initial repository scan
if (this._state === 'initialized' && !this._unsafeRepositories.has(unsafeRepositoryPath)) {
this.showUnsafeRepositoryNotification();
}
this._unsafeRepositories.set(unsafeRepositoryPath, match[2]);
return;
const unsafeRepositoryMatch = /^fatal: detected dubious ownership in repository at \'([^']+)\'[\s\S]*git config --global --add safe\.directory '?([^'\n]+)'?$/m.exec(err.stderr);
if (unsafeRepositoryMatch && unsafeRepositoryMatch.length === 3) {
return { repositoryRoot: path.normalize(unsafeRepositoryMatch[1]), unsafeRepositoryMatch };
}
// noop
this.logger.trace(`Opening repository for path='${repoPath}' failed; ex=${ex}`);
throw err;
}
}
@ -737,6 +794,60 @@ export class Model implements IRemoteSourcePublisherRegistry, IPostCommitCommand
return [...this.pushErrorHandlers];
}
private async isRepositoryOutsideWorkspace(repositoryPath: string): Promise<boolean> {
if (!workspace.workspaceFolders || workspace.workspaceFolders.length === 0) {
return true;
}
const result = await Promise.all(workspace.workspaceFolders.map(async folder => {
const workspaceFolderRealPath = await this.getWorkspaceFolderRealPath(folder);
return pathEquals(workspaceFolderRealPath, repositoryPath) || isDescendant(workspaceFolderRealPath, repositoryPath);
}));
return !result.some(r => r);
}
private async getWorkspaceFolderRealPath(workspaceFolder: WorkspaceFolder): Promise<string> {
let result = this._workspaceFolders.get(workspaceFolder.uri.fsPath);
if (!result) {
result = await fs.promises.realpath(workspaceFolder.uri.fsPath, { encoding: 'utf8' });
this._workspaceFolders.set(workspaceFolder.uri.fsPath, result);
}
return result;
}
private async showParentRepositoryNotification(): Promise<void> {
const message = this.parentRepositories.size === 1 ?
workspace.workspaceFolders !== undefined ?
l10n.t('We found a git repository in one of the parent folders of this workspace. Would you like to open the repository?') :
l10n.t('We found a git repository in one of the parent folders of the open file(s). Would you like to open the repository?') :
workspace.workspaceFolders !== undefined ?
l10n.t('We found git repositories in one of the parent folders of this workspace. Would you like to open the repositories?') :
l10n.t('We found git repositories in one of the parent folders of the open file(s). Would you like to open the repositories?');
const yes = l10n.t('Yes');
const always = l10n.t('Always');
const never = l10n.t('Never');
const choice = await window.showWarningMessage(message, yes, always, never);
if (choice === yes) {
// Open Parent Repositories
commands.executeCommand('git.openRepositoriesInParentFolders');
} else if (choice === always || choice === never) {
// Update setting
const config = workspace.getConfiguration('git');
await config.update('openRepositoryInParentFolders', choice === always ? 'always' : 'never', true);
if (choice === always) {
for (const parentRepository of [...this.parentRepositories.keys()]) {
await this.openParentRepository(parentRepository);
}
}
}
}
private async showUnsafeRepositoryNotification(): Promise<void> {
// If no repositories are open, we will use a welcome view to inform the user
// that a potentially unsafe repository was found so we do not have to show

View file

@ -153,7 +153,7 @@ export const Operation = {
HashObject: { kind: OperationKind.HashObject, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as HashObjectOperation,
Ignore: { kind: OperationKind.Ignore, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as IgnoreOperation,
Log: { kind: OperationKind.Log, blocking: false, readOnly: true, remote: false, retry: false, showProgress: true } as LogOperation,
LogFile: { kind: OperationKind.LogFile, blocking: false, readOnly: true, remote: false, retry: false, showProgress: true } as LogFileOperation,
LogFile: { kind: OperationKind.LogFile, blocking: false, readOnly: true, remote: false, retry: false, showProgress: false } as LogFileOperation,
Merge: { kind: OperationKind.Merge, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as MergeOperation,
MergeAbort: { kind: OperationKind.MergeAbort, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as MergeAbortOperation,
MergeBase: { kind: OperationKind.MergeBase, blocking: false, readOnly: true, remote: false, retry: false, showProgress: true } as MergeBaseOperation,

View file

@ -8,6 +8,11 @@ declare module 'vscode' {
// https://github.com/microsoft/vscode/issues/157734
export namespace workspace {
/**
* An event that is emitted when an edit session identity is about to be requested.
*/
export const onWillCreateEditSessionIdentity: Event<EditSessionIdentityWillCreateEvent>;
/**
*
* @param scheme The URI scheme that this provider can provide edit session identities for.
@ -41,4 +46,26 @@ declare module 'vscode' {
Partial = 50,
None = 0
}
export interface EditSessionIdentityWillCreateEvent {
/**
* A cancellation token.
*/
readonly token: CancellationToken;
/**
* The workspace folder to create an edit session identity for.
*/
readonly workspaceFolder: WorkspaceFolder;
/**
* Allows to pause the event until the provided thenable resolves.
*
* *Note:* This function can only be called during event dispatch.
*
* @param thenable A thenable that delays saving.
*/
waitUntil(thenable: Thenable<any>): void;
}
}

View file

@ -13,9 +13,7 @@
"Other"
],
"activationEvents": [
"*",
"onProfile",
"onProfile:github"
"*"
],
"extensionDependencies": [
"vscode.git-base"
@ -29,8 +27,7 @@
},
"enabledApiProposals": [
"contribShareMenu",
"contribEditSessions",
"profileContentHandlers"
"contribEditSessions"
],
"contributes": {
"commands": [
@ -80,16 +77,16 @@
],
"file/share": [
{
"command": "github.copyVscodeDevLinkFile",
"when": "github.hasGitHubRepo",
"group": "0_vscode@0"
"command": "github.copyVscodeDevLinkFile",
"when": "github.hasGitHubRepo",
"group": "0_vscode@0"
}
],
"editor/context/share": [
{
"command": "github.copyVscodeDevLink",
"when": "github.hasGitHubRepo && resourceScheme != untitled",
"group": "0_vscode@0"
"command": "github.copyVscodeDevLink",
"when": "github.hasGitHubRepo && resourceScheme != untitled",
"group": "0_vscode@0"
}
]
},
@ -119,12 +116,12 @@
{
"view": "scm",
"contents": "%welcome.publishFolder%",
"when": "config.git.enabled && git.state == initialized && workbenchState == folder && git.unsafeRepositoryCount == 0"
"when": "config.git.enabled && git.state == initialized && workbenchState == folder && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0"
},
{
"view": "scm",
"contents": "%welcome.publishWorkspaceFolder%",
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0 && git.unsafeRepositoryCount == 0"
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0 && git.parentRepositoryCount == 0 && git.unsafeRepositoryCount == 0"
}
],
"markdown.previewStyles": [

View file

@ -12,7 +12,6 @@ import { DisposableStore, repositoryHasGitHubRemote } from './util';
import { GithubPushErrorHandler } from './pushErrorHandler';
import { GitBaseExtension } from './typings/git-base';
import { GithubRemoteSourcePublisher } from './remoteSourcePublisher';
import './importExportProfiles';
export function activate(context: ExtensionContext): void {
context.subscriptions.push(initializeGitBaseExtension());

View file

@ -9,7 +9,6 @@
},
"include": [
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
"../../src/vscode-dts/vscode.proposed.profileContentHandlers.d.ts",
"../../src/vscode-dts/vscode.d.ts"
]
}

View file

@ -13,7 +13,7 @@ const path = require('path');
module.exports = withDefaults({
context: path.join(__dirname),
entry: {
extension: './src/node/htmlServerMain.ts',
extension: './src/node/htmlServerNodeMain.ts',
},
output: {
filename: 'htmlServerMain.js',

View file

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
import { URI } from 'vscode-uri';
import { promises as fs } from 'fs';
async function setupMain() {
const l10nLog: string[] = [];
const i10lLocation = process.env['VSCODE_L10N_BUNDLE_LOCATION'];
if (i10lLocation) {
try {
const uri = URI.parse(i10lLocation);
if (uri.scheme === 'file') {
// WORKAROUND for https://github.com/microsoft/vscode-l10n/issues/84. DO NOT COPY.
const contents = await (await fs.readFile(uri.fsPath)).toString();
const bundle = JSON.parse(contents).contents.bundle;
l10n.config({ contents: bundle });
} else {
await l10n.config({ uri: i10lLocation });
}
l10nLog.push(`l10n: Configured to ${i10lLocation.toString()}`);
} catch (e) {
l10nLog.push(`l10n: Problems loading ${i10lLocation.toString()} : ${e}`);
}
}
await import('./htmlServerMain');
l10nLog.forEach(console.log);
}
setupMain();

View file

@ -41,7 +41,11 @@ build().catch(() => process.exit(1));
if (isWatch) {
const watcher = require('@parcel/watcher');
watcher.subscribe(srcDir, () => {
return build();
watcher.subscribe(srcDir, async () => {
try {
await build();
} catch (e) {
console.error(e);
}
});
}

View file

@ -13,7 +13,7 @@ const path = require('path');
const config = withDefaults({
context: path.join(__dirname),
entry: {
extension: './src/node/jsonServerMain.ts',
extension: './src/node/jsonServerNodeMain.ts',
},
output: {
filename: 'jsonServerMain.js',

View file

@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
import { URI } from 'vscode-uri';
import { promises as fs } from 'fs';
async function setupMain() {
const l10nLog: string[] = [];
const i10lLocation = process.env['VSCODE_L10N_BUNDLE_LOCATION'];
if (i10lLocation) {
try {
const uri = URI.parse(i10lLocation);
if (uri.scheme === 'file') {
// WORKAROUND for https://github.com/microsoft/vscode-l10n/issues/84. DO NOT COPY.
const contents = await (await fs.readFile(uri.fsPath)).toString();
const bundle = JSON.parse(contents).contents.bundle;
l10n.config({ contents: bundle });
} else {
await l10n.config({ uri: i10lLocation });
}
l10nLog.push(`l10n: Configured to ${i10lLocation.toString()}`);
} catch (e) {
l10nLog.push(`l10n: Problems loading ${i10lLocation.toString()} : ${e}`);
}
}
await import('./jsonServerMain');
l10nLog.forEach(console.log);
}
setupMain();

View file

@ -37,6 +37,11 @@ function getMangledFileContents(projectPath) {
* @type {webpack.LoaderDefinitionFunction}
*/
module.exports = async function (source, sourceMap, meta) {
if (this.mode !== 'production') {
// Only enable mangling in production builds
return source;
}
if (source !== fs.readFileSync(this.resourcePath).toString()) {
// File content has changed by previous webpack steps.
// Skip mangling.

View file

@ -56,7 +56,11 @@ build().catch(() => process.exit(1));
if (isWatch) {
const watcher = require('@parcel/watcher');
watcher.subscribe(srcDir, () => {
return build();
watcher.subscribe(srcDir, async () => {
try {
await build();
} catch (e) {
console.error(e);
}
});
}

View file

@ -634,7 +634,6 @@ export class AzureActiveDirectoryService {
return new Promise((resolve: (value: vscode.AuthenticationSession) => void, reject) => {
uriEventListener = this._uriHandler.event(async (uri: vscode.Uri) => {
try {
console.log(uri.query);
const query = querystring.parse(uri.query);
let { code, nonce } = query;
if (Array.isArray(code)) {

View file

@ -252,7 +252,7 @@ export const activate: ActivationFunction<void> = (ctx) => {
.traceback {
word-wrap: break-word;
}
.output > span.scrollable {
.output > .scrollable {
overflow-y: scroll;
max-height: var(--notebook-cell-output-max-height);
border: var(--vscode-editorWidget-border);

View file

@ -11,7 +11,7 @@ function patchGrammar(grammar) {
return grammar;
}
const razorGrammarRepo = 'dotnet/razor-tooling';
const razorGrammarRepo = 'dotnet/razor';
const grammarPath = 'src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/syntaxes/aspnetcorerazor.tmLanguage.json';
vscodeGrammarUpdater.update(razorGrammarRepo, grammarPath, './syntaxes/cshtml.tmLanguage.json', grammar => patchGrammar(grammar), 'main');

View file

@ -4,8 +4,8 @@
"component": {
"type": "git",
"git": {
"name": "dotnet/razor-tooling",
"repositoryUrl": "https://github.com/dotnet/razor-tooling",
"name": "dotnet/razor",
"repositoryUrl": "https://github.com/dotnet/razor",
"commitHash": "8d0ae9664cb27276eab36d83e48e88356468ca67"
}
},
@ -38,4 +38,4 @@
}
],
"version": 1
}
}

View file

@ -13,6 +13,7 @@ import { ServiceConnection } from '@vscode/sync-api-common/browser';
import { Requests, ApiService } from '@vscode/sync-api-service';
import { TypeScriptVersionManager } from './versionManager';
import { FileWatcherManager } from './fileWatchingManager';
type BrowserWatchEvent = {
type: 'watchDirectory' | 'watchFile';
recursive?: boolean;
@ -28,17 +29,22 @@ type BrowserWatchEvent = {
};
export class WorkerServerProcess implements TsServerProcess {
@memoize
private static get output(): vscode.OutputChannel {
return vscode.window.createOutputChannel(vscode.l10n.t("TypeScript Server Log"));
}
public static fork(
version: TypeScriptVersion,
args: readonly string[],
_kind: TsServerProcessKind,
kind: TsServerProcessKind,
_configuration: TypeScriptServiceConfiguration,
_versionManager: TypeScriptVersionManager,
extensionUri: vscode.Uri,
) {
const tsServerPath = version.tsServerPath;
const worker = new Worker(tsServerPath);
return new WorkerServerProcess(worker, extensionUri, [
return new WorkerServerProcess(kind, worker, extensionUri, [
...args,
// Explicitly give TS Server its path so it can
@ -47,10 +53,15 @@ export class WorkerServerProcess implements TsServerProcess {
]);
}
private static idPool = 0;
private readonly id = WorkerServerProcess.idPool++;
private readonly _onDataHandlers = new Set<(data: Proto.Response) => void>();
private readonly _onErrorHandlers = new Set<(err: Error) => void>();
private readonly _onExitHandlers = new Set<(code: number | null, signal: string | null) => void>();
private readonly watches = new FileWatcherManager();
/** For communicating with TS server synchronously */
private readonly tsserver: MessagePort;
/** For communicating watches asynchronously */
@ -59,6 +70,7 @@ export class WorkerServerProcess implements TsServerProcess {
private readonly syncFs: MessagePort;
public constructor(
private readonly kind: TsServerProcessKind,
/** For logging and initial setup */
private readonly mainChannel: Worker,
extensionUri: vscode.Uri,
@ -70,6 +82,7 @@ export class WorkerServerProcess implements TsServerProcess {
this.tsserver = tsserverChannel.port2;
this.watcher = watcherChannel.port2;
this.syncFs = syncChannel.port2;
this.tsserver.onmessage = (event) => {
if (event.data.type === 'log') {
console.error(`unexpected log message on tsserver channel: ${JSON.stringify(event)}`);
@ -79,6 +92,7 @@ export class WorkerServerProcess implements TsServerProcess {
handler(event.data);
}
};
this.watcher.onmessage = (event: MessageEvent<BrowserWatchEvent>) => {
switch (event.data.type) {
case 'dispose': {
@ -98,14 +112,16 @@ export class WorkerServerProcess implements TsServerProcess {
console.error(`unexpected message on watcher channel: ${JSON.stringify(event)}`);
}
};
mainChannel.onmessage = (msg: any) => {
// for logging only
if (msg.data.type === 'log') {
this.output.append(msg.data.body);
this.appendOutput(msg.data.body);
return;
}
console.error(`unexpected message on main channel: ${JSON.stringify(msg)}`);
};
mainChannel.onerror = (err: ErrorEvent) => {
console.error('error! ' + JSON.stringify(err));
for (const handler of this._onErrorHandlers) {
@ -113,20 +129,17 @@ export class WorkerServerProcess implements TsServerProcess {
handler(err.error);
}
};
this.output.append(`creating new MessageChannel and posting its port2 + args: ${args.join(' ')}\n`);
this.appendOutput(`creating new MessageChannel and posting its port2 + args: ${args.join(' ')}\n`);
mainChannel.postMessage(
{ args, extensionUri },
[syncChannel.port1, tsserverChannel.port1, watcherChannel.port1]
);
const connection = new ServiceConnection<Requests>(syncChannel.port2);
new ApiService('vscode-wasm-typescript', connection);
connection.signalReady();
this.output.append('done constructing WorkerServerProcess\n');
}
@memoize
private get output(): vscode.OutputChannel {
return vscode.window.createOutputChannel(vscode.l10n.t("TypeScript Server Log"));
this.appendOutput('done constructing WorkerServerProcess\n');
}
write(serverRequest: Proto.Request): void {
@ -152,5 +165,9 @@ export class WorkerServerProcess implements TsServerProcess {
this.watcher.close();
this.syncFs.close();
}
private appendOutput(msg: string) {
WorkerServerProcess.output.append(`(${this.id} - ${this.kind}) ${msg}`);
}
}

View file

@ -675,27 +675,22 @@ export default class TypeScriptServiceClient extends Disposable implements IType
return undefined;
}
switch (resource.scheme) {
case fileSchemes.file:
{
let result = resource.fsPath;
if (!result) {
return undefined;
}
result = path.normalize(result);
if (resource.scheme === fileSchemes.file && !isWeb()) {
let result = resource.fsPath;
if (!result) {
return undefined;
}
result = path.normalize(result);
// Both \ and / must be escaped in regular expressions
return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/');
}
default:
{
return (this.isProjectWideIntellisenseOnWebEnabled() ? '' : this.inMemoryResourcePrefix)
+ '/' + resource.scheme
+ '/' + (resource.authority || this.emptyAuthority)
+ (resource.path.startsWith('/') ? resource.path : '/' + resource.path)
+ (resource.fragment ? '#' + resource.fragment : '');
}
// Both \ and / must be escaped in regular expressions
return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/');
}
return (this.isProjectWideIntellisenseOnWebEnabled() ? '' : this.inMemoryResourcePrefix)
+ '/' + resource.scheme
+ '/' + (resource.authority || this.emptyAuthority)
+ (resource.path.startsWith('/') ? resource.path : '/' + resource.path)
+ (resource.fragment ? '#' + resource.fragment : '');
}
public toPath(resource: vscode.Uri): string | undefined {

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.75.0",
"distro": "f98abe6153bfce4838ff1dfc01de4bae94058e67",
"distro": "731b87488b198abcd49160d32e4962ceceafd128",
"author": {
"name": "Microsoft Corporation"
},
@ -78,7 +78,7 @@
"native-is-elevated": "0.4.3",
"native-keymap": "3.3.2",
"native-watchdog": "1.4.1",
"node-pty": "0.11.0-beta11",
"node-pty": "0.11.0-beta27",
"spdlog": "^0.13.0",
"tas-client-umd": "0.1.6",
"v8-inspect-profiler": "^0.1.0",
@ -87,13 +87,13 @@
"vscode-proxy-agent": "^0.12.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "8.0.0",
"xterm": "5.2.0-beta.10",
"xterm-addon-canvas": "0.4.0-beta.6",
"xterm": "5.2.0-beta.17",
"xterm-addon-canvas": "0.4.0-beta.7",
"xterm-addon-search": "0.11.0",
"xterm-addon-serialize": "0.9.0",
"xterm-addon-unicode11": "0.5.0",
"xterm-addon-webgl": "0.15.0-beta.4",
"xterm-headless": "5.2.0-beta.10",
"xterm-headless": "5.2.0-beta.17",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
@ -132,7 +132,7 @@
"@vscode/l10n-dev": "0.0.21",
"@vscode/telemetry-extractor": "^1.9.8",
"@vscode/test-web": "^0.0.32",
"@vscode/vscode-perf": "^0.0.2",
"@vscode/vscode-perf": "^0.0.5",
"ansi-colors": "^3.2.3",
"asar": "^3.0.3",
"chromium-pickle-js": "^0.2.0",
@ -209,7 +209,7 @@
"ts-loader": "^9.2.7",
"ts-node": "^10.9.1",
"tsec": "0.1.4",
"typescript": "^5.0.0-dev.20230109",
"typescript": "^5.0.0-dev.20230117",
"typescript-formatter": "7.1.0",
"underscore": "^1.12.1",
"util": "^0.12.4",
@ -233,7 +233,7 @@
"@vscode/windows-registry": "1.0.6",
"windows-foreground-love": "0.4.0",
"windows-mutex": "0.4.1",
"windows-process-tree": "0.3.4"
"windows-process-tree": "0.4.0"
},
"resolutions": {
"elliptic": "^6.5.3",

View file

@ -17,25 +17,25 @@
"keytar": "7.9.0",
"minimist": "^1.2.6",
"native-watchdog": "1.4.1",
"node-pty": "0.11.0-beta11",
"node-pty": "0.11.0-beta27",
"spdlog": "^0.13.0",
"tas-client-umd": "0.1.6",
"vscode-oniguruma": "1.7.0",
"vscode-proxy-agent": "^0.12.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "8.0.0",
"xterm": "5.2.0-beta.10",
"xterm-addon-canvas": "0.4.0-beta.6",
"xterm": "5.2.0-beta.17",
"xterm-addon-canvas": "0.4.0-beta.7",
"xterm-addon-search": "0.11.0",
"xterm-addon-serialize": "0.9.0",
"xterm-addon-unicode11": "0.5.0",
"xterm-addon-webgl": "0.15.0-beta.4",
"xterm-headless": "5.2.0-beta.10",
"xterm-headless": "5.2.0-beta.17",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
"optionalDependencies": {
"@vscode/windows-registry": "1.0.6",
"windows-process-tree": "0.3.4"
"windows-process-tree": "0.4.0"
}
}

View file

@ -11,8 +11,8 @@
"tas-client-umd": "0.1.6",
"vscode-oniguruma": "1.7.0",
"vscode-textmate": "8.0.0",
"xterm": "5.2.0-beta.10",
"xterm-addon-canvas": "0.4.0-beta.6",
"xterm": "5.2.0-beta.17",
"xterm-addon-canvas": "0.4.0-beta.7",
"xterm-addon-search": "0.11.0",
"xterm-addon-unicode11": "0.5.0",
"xterm-addon-webgl": "0.15.0-beta.4"

View file

@ -68,10 +68,10 @@ vscode-textmate@8.0.0:
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d"
integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==
xterm-addon-canvas@0.4.0-beta.6:
version "0.4.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0-beta.6.tgz#f8cb09ef980f1fa9d73f067e00f7a879c374ad68"
integrity sha512-x5OY0VOJxqvXdyXpW9aug3vaeQX/+r7TZk13MujReuJRLRAjCHaH6ep6g9ZOVlqa8VCBWPwmm/eXH05SGUbnQQ==
xterm-addon-canvas@0.4.0-beta.7:
version "0.4.0-beta.7"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0-beta.7.tgz#ae365d8e10c900292186529f70f7f275ac94b3d5"
integrity sha512-r1hbQTsulI49orR5G3qWrJCwn2dKsEUCrgj6xsmgXuTeoUcGfed6lly+MvYlL3P8aPrxS2fC2TEzSM0Au4SX+w==
xterm-addon-search@0.11.0:
version "0.11.0"
@ -88,7 +88,7 @@ xterm-addon-webgl@0.15.0-beta.4:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0-beta.4.tgz#d03a98e446372a5dbb7d92075d1f125eec23b030"
integrity sha512-W9N0+5i3trQhgBOHDsnNiBbBiJpleFenY668wWaZ9GlvWseCTnjnWis1kfnM9WASDh/0+7aOjWrD089o+QeHGQ==
xterm@5.2.0-beta.10:
version "5.2.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.10.tgz#33e67a8397937dd8b731a2f315c67f4bd63f3c28"
integrity sha512-3zVxU/0XrUWpvOIU/KkXREweq7hCxNGFt4asT4D/SsRlRKYOnO+vooz1CjLO6USY++iHXicgf8PdgRDeYj5fFQ==
xterm@5.2.0-beta.17:
version "5.2.0-beta.17"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.17.tgz#034bf7cac9aff2adc0f2958e09a62203ace7c48e"
integrity sha512-pLkLhWh1XPkZnSNyxY1A/2WOzMRq0axJO69vCV+gu6/do3W/EeMtyPqwZSmIHF9s37t3CQlN8RsMHUpdR61VCQ==

View file

@ -458,16 +458,16 @@ ms@2.1.2, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nan@^2.13.2:
version "2.14.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
nan@^2.14.0:
version "2.15.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
nan@^2.17.0:
version "2.17.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
napi-build-utils@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
@ -505,12 +505,12 @@ node-gyp-build@^4.3.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==
node-pty@0.11.0-beta11:
version "0.11.0-beta11"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta11.tgz#10843516868129c26a97253903c46fe0e4520eb0"
integrity sha512-Gw58duqHle4k/BunssCE1CUKKWipRQZTUFhaTegkKC19fw3IXsvillblLUuD2bQL42+3mQCAFSgTDo+OsJzYCQ==
node-pty@0.11.0-beta27:
version "0.11.0-beta27"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta27.tgz#13ebfb687aff23af3b38991e676ac0fb92accb82"
integrity sha512-HkP1lHsgOgXroEMuFt/2hNkyI+roSSKIMKkyaW3g/NVNY3j5gpYD2YM05EbYlJbjaUFAWqbJzoLIVs2g+A+B8A==
dependencies:
nan "^2.14.0"
nan "^2.17.0"
npmlog@^4.0.1:
version "4.1.2"
@ -829,22 +829,22 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2 || 3 || 4"
windows-process-tree@0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.3.4.tgz#6bc4b8010129c30ff95bcd333b9f94744dd3c4fb"
integrity sha512-rtSX73i9OnkDxSdBP9c1YBunEwheZdO/hjRwNk9uSoWqO92x0zDRGfIIK0MtUn8gZZD+2kPEVpj5MmfNl7JpJA==
windows-process-tree@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.4.0.tgz#31ac49c5da557e628ce7e37a5800972173d3349a"
integrity sha512-9LunDnc1WwuhyLeTAXMFX8wbActGJtDCBaiapQXFYk/nO4W4X9YxOKV5g/lQL3XX69QYxveDbjVVrdnTt1qqCQ==
dependencies:
nan "^2.13.2"
nan "^2.17.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xterm-addon-canvas@0.4.0-beta.6:
version "0.4.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0-beta.6.tgz#f8cb09ef980f1fa9d73f067e00f7a879c374ad68"
integrity sha512-x5OY0VOJxqvXdyXpW9aug3vaeQX/+r7TZk13MujReuJRLRAjCHaH6ep6g9ZOVlqa8VCBWPwmm/eXH05SGUbnQQ==
xterm-addon-canvas@0.4.0-beta.7:
version "0.4.0-beta.7"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0-beta.7.tgz#ae365d8e10c900292186529f70f7f275ac94b3d5"
integrity sha512-r1hbQTsulI49orR5G3qWrJCwn2dKsEUCrgj6xsmgXuTeoUcGfed6lly+MvYlL3P8aPrxS2fC2TEzSM0Au4SX+w==
xterm-addon-search@0.11.0:
version "0.11.0"
@ -866,15 +866,15 @@ xterm-addon-webgl@0.15.0-beta.4:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0-beta.4.tgz#d03a98e446372a5dbb7d92075d1f125eec23b030"
integrity sha512-W9N0+5i3trQhgBOHDsnNiBbBiJpleFenY668wWaZ9GlvWseCTnjnWis1kfnM9WASDh/0+7aOjWrD089o+QeHGQ==
xterm-headless@5.2.0-beta.10:
version "5.2.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.10.tgz#fc7b11b0395f6bb934b0c9373b412bc4d3247148"
integrity sha512-jjylqERzLWWrPLpehL1v0Y3JaZqQksoqE04g5H+tNceQemoBlIpbA5OgPrbcjz5xxFIR9mVWppFR7klWox5/Sg==
xterm-headless@5.2.0-beta.17:
version "5.2.0-beta.17"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.17.tgz#7ba458d6de58e7278e68b25e666a5e91fcf98ca9"
integrity sha512-YqOKhRCbHcwuKaCbkIFkZX8ovGQNOz0pdlguJGkPM1g1yuucOJ5kudA+iEFSkA9KW5fgADdSUXJFRDrNO6RjbQ==
xterm@5.2.0-beta.10:
version "5.2.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.10.tgz#33e67a8397937dd8b731a2f315c67f4bd63f3c28"
integrity sha512-3zVxU/0XrUWpvOIU/KkXREweq7hCxNGFt4asT4D/SsRlRKYOnO+vooz1CjLO6USY++iHXicgf8PdgRDeYj5fFQ==
xterm@5.2.0-beta.17:
version "5.2.0-beta.17"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.17.tgz#034bf7cac9aff2adc0f2958e09a62203ace7c48e"
integrity sha512-pLkLhWh1XPkZnSNyxY1A/2WOzMRq0axJO69vCV+gu6/do3W/EeMtyPqwZSmIHF9s37t3CQlN8RsMHUpdR61VCQ==
yallist@^4.0.0:
version "4.0.0"

View file

@ -7,23 +7,25 @@
const path = require('path');
const perf = require('@vscode/vscode-perf');
const minimist = require('minimist');
const VSCODE_FOLDER = path.join(__dirname, '..');
async function main() {
const args = [...process.argv];
/** @type {string | undefined} */
let build = undefined;
if (args.indexOf('--help') === -1 && args.indexOf('-h') === -1) {
// get build arg from args
let buildArgIndex = args.indexOf('--build');
buildArgIndex = buildArgIndex === -1 ? args.indexOf('-b') : buildArgIndex;
if (buildArgIndex === -1) {
args.push('--build');
args.push(getLocalCLIPath());
build = getLocalCLIPath();
} else {
const exePath = args[buildArgIndex + 1];
args.splice(buildArgIndex + 1, 1, getExePath(exePath));
build = getExePath(args[buildArgIndex + 1]);
args.splice(buildArgIndex + 1, 1);
}
args.push('--folder');
@ -32,7 +34,10 @@ async function main() {
args.push(path.join(VSCODE_FOLDER, 'package.json'));
}
await perf(args);
await perf.run(build ? {
...minimist(args),
build
} : undefined);
}
/**

10
src/bootstrap.js vendored
View file

@ -32,8 +32,16 @@
if (typeof process !== 'undefined' && !process.env['VSCODE_HANDLES_SIGPIPE']) {
// Workaround for Electron not installing a handler to ignore SIGPIPE
// (https://github.com/electron/electron/issues/13254)
let didLogAboutSIGPIPE = false;
process.on('SIGPIPE', () => {
console.error(new Error('Unexpected SIGPIPE'));
// See https://github.com/microsoft/vscode-remote-release/issues/6543
// We would normally install a SIGPIPE listener in bootstrap.js
// But in certain situations, the console itself can be in a broken pipe state
// so logging SIGPIPE to the console will cause an infinite async loop
if (!didLogAboutSIGPIPE) {
didLogAboutSIGPIPE = true;
console.error(new Error(`Unexpected SIGPIPE`));
}
});
}

View file

@ -575,11 +575,14 @@ async function resolveNlsConfiguration() {
// VS Code moves to Electron 22.
// Ref https://github.com/microsoft/vscode/issues/159813
// and https://github.com/electron/electron/pull/36035
// if ('getPreferredSystemLanguages' in app
// && typeof app.getPreferredSystemLanguages === 'function'
// && app.getPreferredSystemLanguages().length) {
// appLocale = app.getPreferredSystemLanguages()[0];
// }
if (process.platform === 'win32'
&& 'getPreferredSystemLanguages' in app
&& typeof app.getPreferredSystemLanguages === 'function'
&& app.getPreferredSystemLanguages().length) {
// Use the most preferred OS language for language recommendation.
appLocale = app.getPreferredSystemLanguages()[0];
}
if (!appLocale) {
nlsConfiguration = { locale: 'en', availableLanguages: {} };
} else {
@ -587,6 +590,12 @@ async function resolveNlsConfiguration() {
// See above the comment about the loader and case sensitiveness
appLocale = appLocale.toLowerCase();
if (appLocale.startsWith('zh-hans')) {
appLocale = 'zh-cn';
} else if (appLocale.startsWith('zh-hant')) {
appLocale = 'zh-tw';
}
const { getNLSConfiguration } = require('./vs/base/node/languagePacks');
nlsConfiguration = await getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
if (!nlsConfiguration) {

View file

@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IAction, IActionRunner } from 'vs/base/common/actions';
@ -19,7 +20,7 @@ export interface IContextMenuDelegate {
getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number };
getActions(): readonly IAction[];
getCheckedActionsRepresentation?(action: IAction): 'radio' | 'checkbox';
getActionViewItem?(action: IAction): IActionViewItem | undefined;
getActionViewItem?(action: IAction, options: IActionViewItemOptions): IActionViewItem | undefined;
getActionsContext?(event?: IContextMenuEvent): unknown;
getKeyBinding?(action: IAction): ResolvedKeybinding | undefined;
getMenuClassName?(): string;

View file

@ -1818,8 +1818,23 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia
el.id = match.groups['id'];
}
const classNames = [];
if (match.groups['class']) {
el.className = match.groups['class'].replace(/\./g, ' ').trim();
for (const className of match.groups['class'].split('.')) {
if (className !== '') {
classNames.push(className);
}
}
}
if (attributes.className !== undefined) {
for (const className of attributes.className.split('.')) {
if (className !== '') {
classNames.push(className);
}
}
}
if (classNames.length > 0) {
el.className = classNames.join(' ');
}
const result: Record<string, HTMLElement> = {};
@ -1842,7 +1857,9 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia
}
for (const [key, value] of Object.entries(attributes)) {
if (key === 'style') {
if (key === 'className') {
continue;
} else if (key === 'style') {
for (const [cssKey, cssValue] of Object.entries(value)) {
el.style.setProperty(
camelCaseToHyphenCase(cssKey),

View file

@ -11,7 +11,7 @@ import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { ICustomHover, setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
import { ISelectBoxOptions, ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { ISelectBoxOptions, ISelectBoxStyles, ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { IToggleStyles } from 'vs/base/browser/ui/toggle/toggle';
import { Action, ActionRunner, IAction, IActionChangeEvent, IActionRunner, Separator } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
@ -418,10 +418,10 @@ export class ActionViewItem extends BaseActionViewItem {
export class SelectActionViewItem extends BaseActionViewItem {
protected selectBox: SelectBox;
constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) {
constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) {
super(ctx, action);
this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
this.selectBox = new SelectBox(options, selected, contextViewProvider, styles, selectBoxOptions);
this.selectBox.setFocusable(false);
this._register(this.selectBox);

View file

@ -25,7 +25,7 @@ export interface IActionViewItem extends IDisposable {
}
export interface IActionViewItemProvider {
(action: IAction): IActionViewItem | undefined;
(action: IAction, options: IActionViewItemOptions): IActionViewItem | undefined;
}
export const enum ActionsOrientation {
@ -347,12 +347,13 @@ export class ActionBar extends Disposable implements IActionRunner {
let item: IActionViewItem | undefined;
const viewItemOptions = { hoverDelegate: this.options.hoverDelegate, ...options };
if (this.options.actionViewItemProvider) {
item = this.options.actionViewItemProvider(action);
item = this.options.actionViewItemProvider(action, viewItemOptions);
}
if (!item) {
item = new ActionViewItem(this.context, action, { hoverDelegate: this.options.hoverDelegate, ...options });
item = new ActionViewItem(this.context, action, viewItemOptions);
}
// Prevent native context menu on actions

View file

@ -429,8 +429,8 @@ export class Dialog extends Disposable {
this.shadowElement.style.boxShadow = shadowColor;
this.element.style.color = fgColor?.toString() ?? '';
this.element.style.backgroundColor = bgColor?.toString() ?? '';
this.element.style.color = fgColor ?? '';
this.element.style.backgroundColor = bgColor ?? '';
this.element.style.border = border;
// TODO fix

View file

@ -207,7 +207,7 @@ export class DropdownMenu extends BaseDropdown {
getAnchor: () => this.element,
getActions: () => this.actions,
getActionsContext: () => this.menuOptions ? this.menuOptions.context : null,
getActionViewItem: action => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action) : undefined,
getActionViewItem: (action, options) => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action, options) : undefined,
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,
getMenuClassName: () => this.menuClassName,
onHide: () => this.onHide(),

View file

@ -466,8 +466,8 @@ export class InputBox extends Widget {
spanElement.classList.add(this.classForType(this.message.type));
const styles = this.stylesForType(this.message.type);
spanElement.style.backgroundColor = styles.background ? styles.background.toString() : '';
spanElement.style.color = styles.foreground ? styles.foreground.toString() : '';
spanElement.style.backgroundColor = styles.background ?? '';
spanElement.style.color = styles.foreground ?? '';
spanElement.style.border = styles.border ? `1px solid ${styles.border}` : '';
dom.append(div, spanElement);

View file

@ -9,7 +9,6 @@ import { Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IPagedModel } from 'vs/base/common/paging';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IThemable } from 'vs/base/common/styler';
import 'vs/css!./list';
import { IListContextMenuEvent, IListEvent, IListMouseEvent, IListRenderer, IListVirtualDelegate } from './list';
import { IListAccessibilityProvider, IListOptions, IListOptionsUpdate, IListStyles, List, TypeNavigationMode } from './listWidget';
@ -119,7 +118,7 @@ function fromPagedListOptions<T>(modelProvider: () => IPagedModel<T>, options: I
};
}
export class PagedList<T> implements IThemable, IDisposable {
export class PagedList<T> implements IDisposable {
private list: List<number>;
private _model!: IPagedModel<T>;

View file

@ -212,6 +212,52 @@ class ListViewAccessibilityProvider<T> implements Required<IListViewAccessibilit
}
}
export interface IListView<T> extends ISpliceable<T>, IDisposable {
readonly domId: string;
readonly domNode: HTMLElement;
readonly containerDomNode: HTMLElement;
readonly scrollableElementDomNode: HTMLElement;
readonly length: number;
readonly contentHeight: number;
readonly onDidChangeContentHeight: Event<number>;
readonly renderHeight: number;
readonly scrollHeight: number;
readonly firstVisibleIndex: number;
readonly lastVisibleIndex: number;
onDidScroll: Event<ScrollEvent>;
onWillScroll: Event<ScrollEvent>;
onMouseClick: Event<IListMouseEvent<T>>;
onMouseDblClick: Event<IListMouseEvent<T>>;
onMouseMiddleClick: Event<IListMouseEvent<T>>;
onMouseUp: Event<IListMouseEvent<T>>;
onMouseDown: Event<IListMouseEvent<T>>;
onMouseOver: Event<IListMouseEvent<T>>;
onMouseMove: Event<IListMouseEvent<T>>;
onMouseOut: Event<IListMouseEvent<T>>;
onContextMenu: Event<IListMouseEvent<T>>;
onTouchStart: Event<IListTouchEvent<T>>;
onTap: Event<IListGestureEvent<T>>;
element(index: number): T;
domElement(index: number): HTMLElement | null;
getElementDomId(index: number): string;
elementHeight(index: number): number;
elementTop(index: number): number;
indexOf(element: T): number;
indexAt(position: number): number;
indexAfter(position: number): number;
updateOptions(options: IListViewOptionsUpdate): void;
getScrollTop(): number;
setScrollTop(scrollTop: number, reuseAnimation?: boolean): void;
getScrollLeft(): number;
setScrollLeft(scrollLeft: number): void;
delegateScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent): void;
delegateVerticalScrollbarPointerDown(browserEvent: PointerEvent): void;
updateWidth(index: number): void;
updateElementHeight(index: number, size: number | undefined, anchorIndex: number | null): void;
rerender(): void;
layout(height?: number, width?: number): void;
}
/**
* The {@link ListView} is a virtual scrolling engine.
*
@ -222,7 +268,7 @@ class ListViewAccessibilityProvider<T> implements Required<IListViewAccessibilit
* @remarks It is a low-level widget, not meant to be used directly. Refer to the
* List widget instead.
*/
export class ListView<T> implements ISpliceable<T>, IDisposable {
export class ListView<T> implements IListView<T> {
private static InstanceCount = 0;
readonly domId = `list_id_${++ListView.InstanceCount}`;
@ -758,7 +804,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
// Render
private render(previousRenderRange: IRange, renderTop: number, renderHeight: number, renderLeft: number | undefined, scrollWidth: number | undefined, updateItemsInDOM: boolean = false): void {
protected render(previousRenderRange: IRange, renderTop: number, renderHeight: number, renderLeft: number | undefined, scrollWidth: number | undefined, updateItemsInDOM: boolean = false): void {
const renderRange = this.getRenderRange(renderTop, renderHeight);
const rangesToInsert = Range.relativeComplement(renderRange, previousRenderRange);

View file

@ -20,15 +20,13 @@ import { matchesPrefix } from 'vs/base/common/filters';
import { KeyCode } from 'vs/base/common/keyCodes';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { clamp } from 'vs/base/common/numbers';
import { mixin } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { ISpliceable } from 'vs/base/common/sequence';
import { IThemable } from 'vs/base/common/styler';
import { isNumber } from 'vs/base/common/types';
import 'vs/css!./list';
import { IIdentityProvider, IKeyboardNavigationDelegate, IKeyboardNavigationLabelProvider, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IListEvent, IListGestureEvent, IListMouseEvent, IListRenderer, IListTouchEvent, IListVirtualDelegate, ListError } from './list';
import { IListViewAccessibilityProvider, IListViewDragAndDrop, IListViewOptions, IListViewOptionsUpdate, ListView } from './listView';
import { IListView, IListViewAccessibilityProvider, IListViewDragAndDrop, IListViewOptions, IListViewOptionsUpdate, ListView } from './listView';
interface ITraitChangeEvent {
indexes: number[];
@ -222,7 +220,7 @@ class TraitSpliceable<T> implements ISpliceable<T> {
constructor(
private trait: Trait<T>,
private view: ListView<T>,
private view: IListView<T>,
private identityProvider?: IIdentityProvider<T>
) { }
@ -289,7 +287,7 @@ class KeyboardController<T> implements IDisposable {
constructor(
private list: List<T>,
private view: ListView<T>,
private view: IListView<T>,
options: IListOptions<T>
) {
this.onKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(this.onEnter, this, this.disposables);
@ -421,7 +419,7 @@ class TypeNavigationController<T> implements IDisposable {
constructor(
private list: List<T>,
private view: ListView<T>,
private view: IListView<T>,
private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider<T>,
private keyboardNavigationEventFilter: IKeyboardNavigationEventFilter,
private delegate: IKeyboardNavigationDelegate
@ -535,7 +533,7 @@ class DOMFocusController<T> implements IDisposable {
constructor(
private list: List<T>,
private view: ListView<T>
private view: IListView<T>
) {
const onKeyDown = this.disposables.add(Event.chain(this.disposables.add(new DomEmitter(view.domNode, 'keydown')).event))
.filter(e => !isInputElement(e.target as HTMLElement))
@ -797,11 +795,7 @@ export class DefaultStyleController implements IStyleController {
const content: string[] = [];
if (styles.listBackground) {
if (styles.listBackground.isOpaque()) {
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
} else if (!platform.isMacintosh) { // subpixel AA doesn't exist in macOS
console.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);
}
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
}
if (styles.listFocusBackground) {
@ -972,47 +966,59 @@ export interface IListOptions<T> extends IListOptionsUpdate {
}
export interface IListStyles {
listBackground?: Color;
listFocusBackground?: Color;
listFocusForeground?: Color;
listActiveSelectionBackground?: Color;
listActiveSelectionForeground?: Color;
listActiveSelectionIconForeground?: Color;
listFocusAndSelectionOutline?: Color;
listFocusAndSelectionBackground?: Color;
listFocusAndSelectionForeground?: Color;
listInactiveSelectionBackground?: Color;
listInactiveSelectionIconForeground?: Color;
listInactiveSelectionForeground?: Color;
listInactiveFocusForeground?: Color;
listInactiveFocusBackground?: Color;
listHoverBackground?: Color;
listHoverForeground?: Color;
listDropBackground?: Color;
listFocusOutline?: Color;
listInactiveFocusOutline?: Color;
listSelectionOutline?: Color;
listHoverOutline?: Color;
treeIndentGuidesStroke?: Color;
tableColumnsBorder?: Color;
tableOddRowsBackgroundColor?: Color;
listBackground: string | undefined;
listFocusBackground: string | undefined;
listFocusForeground: string | undefined;
listActiveSelectionBackground: string | undefined;
listActiveSelectionForeground: string | undefined;
listActiveSelectionIconForeground: string | undefined;
listFocusAndSelectionOutline: string | undefined;
listFocusAndSelectionBackground: string | undefined;
listFocusAndSelectionForeground: string | undefined;
listInactiveSelectionBackground: string | undefined;
listInactiveSelectionIconForeground: string | undefined;
listInactiveSelectionForeground: string | undefined;
listInactiveFocusForeground: string | undefined;
listInactiveFocusBackground: string | undefined;
listHoverBackground: string | undefined;
listHoverForeground: string | undefined;
listDropBackground: string | undefined;
listFocusOutline: string | undefined;
listInactiveFocusOutline: string | undefined;
listSelectionOutline: string | undefined;
listHoverOutline: string | undefined;
treeIndentGuidesStroke: string | undefined;
treeInactiveIndentGuidesStroke: string | undefined;
tableColumnsBorder: string | undefined;
tableOddRowsBackgroundColor: string | undefined;
}
const defaultStyles: IListStyles = {
listFocusBackground: Color.fromHex('#7FB0D0'),
listActiveSelectionBackground: Color.fromHex('#0E639C'),
listActiveSelectionForeground: Color.fromHex('#FFFFFF'),
listActiveSelectionIconForeground: Color.fromHex('#FFFFFF'),
listFocusAndSelectionOutline: Color.fromHex('#90C2F9'),
listFocusAndSelectionBackground: Color.fromHex('#094771'),
listFocusAndSelectionForeground: Color.fromHex('#FFFFFF'),
listInactiveSelectionBackground: Color.fromHex('#3F3F46'),
listInactiveSelectionIconForeground: Color.fromHex('#FFFFFF'),
listHoverBackground: Color.fromHex('#2A2D2E'),
listDropBackground: Color.fromHex('#383B3D'),
treeIndentGuidesStroke: Color.fromHex('#a9a9a9'),
tableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2),
tableOddRowsBackgroundColor: Color.fromHex('#cccccc').transparent(0.04)
export const unthemedListStyles: IListStyles = {
listFocusBackground: '#7FB0D0',
listActiveSelectionBackground: '#0E639C',
listActiveSelectionForeground: '#FFFFFF',
listActiveSelectionIconForeground: '#FFFFFF',
listFocusAndSelectionOutline: '#90C2F9',
listFocusAndSelectionBackground: '#094771',
listFocusAndSelectionForeground: '#FFFFFF',
listInactiveSelectionBackground: '#3F3F46',
listInactiveSelectionIconForeground: '#FFFFFF',
listHoverBackground: '#2A2D2E',
listDropBackground: '#383B3D',
treeIndentGuidesStroke: '#a9a9a9',
treeInactiveIndentGuidesStroke: Color.fromHex('#a9a9a9').transparent(0.4).toString(),
tableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2).toString(),
tableOddRowsBackgroundColor: Color.fromHex('#cccccc').transparent(0.04).toString(),
listBackground: undefined,
listFocusForeground: undefined,
listInactiveSelectionForeground: undefined,
listInactiveFocusForeground: undefined,
listInactiveFocusBackground: undefined,
listHoverForeground: undefined,
listFocusOutline: undefined,
listInactiveFocusOutline: undefined,
listSelectionOutline: undefined,
listHoverOutline: undefined
};
const DefaultOptions: IListOptions<any> = {
@ -1241,13 +1247,13 @@ class ListViewDragAndDrop<T> implements IListViewDragAndDrop<T> {
* - Dynamic element height support
* - Drag-and-drop support
*/
export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
export class List<T> implements ISpliceable<T>, IDisposable {
private focus = new Trait<T>('focused');
private selection: Trait<T>;
private anchor = new Trait<T>('anchor');
private eventBufferer = new EventBufferer();
protected view: ListView<T>;
protected view: IListView<T>;
private spliceable: ISpliceable<T>;
private styleController: IStyleController;
private typeNavigationController?: TypeNavigationController<T>;
@ -1339,8 +1345,6 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
this.selection = new SelectionTrait(role !== 'listbox');
mixin(_options, defaultStyles, false);
const baseRenderers: IListRenderer<T, ITraitTemplateData>[] = [this.focus.renderer, this.selection.renderer];
this.accessibilityProvider = _options.accessibilityProvider;
@ -1358,7 +1362,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
dnd: _options.dnd && new ListViewDragAndDrop(this, _options.dnd)
};
this.view = new ListView(container, virtualDelegate, renderers, viewOptions);
this.view = this.createListView(container, virtualDelegate, renderers, viewOptions);
this.view.domNode.setAttribute('role', role);
if (_options.styleController) {
@ -1409,6 +1413,10 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
}
}
protected createListView(container: HTMLElement, virtualDelegate: IListVirtualDelegate<T>, renderers: IListRenderer<any, any>[], viewOptions: IListViewOptions<T>): IListView<T> {
return new ListView(container, virtualDelegate, renderers, viewOptions);
}
protected createMouseController(options: IListOptions<T>): MouseController<T> {
return new MouseController(this);
}

View file

@ -16,7 +16,6 @@ import { EmptySubmenuAction, IAction, IActionRunner, Separator, SubmenuAction }
import { RunOnceScheduler } from 'vs/base/common/async';
import { Codicon, getCodiconFontCharacters } from 'vs/base/common/codicons';
import { ThemeIcon } from 'vs/base/common/themables';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { stripIcons } from 'vs/base/common/iconLabels';
import { KeyCode } from 'vs/base/common/keyCodes';
@ -50,20 +49,35 @@ export interface IMenuOptions {
}
export interface IMenuStyles {
shadowColor?: Color;
borderColor?: Color;
foregroundColor?: Color;
backgroundColor?: Color;
selectionForegroundColor?: Color;
selectionBackgroundColor?: Color;
selectionBorderColor?: Color;
separatorColor?: Color;
scrollbarShadow?: Color;
scrollbarSliderBackground?: Color;
scrollbarSliderHoverBackground?: Color;
scrollbarSliderActiveBackground?: Color;
shadowColor: string | undefined;
borderColor: string | undefined;
foregroundColor: string | undefined;
backgroundColor: string | undefined;
selectionForegroundColor: string | undefined;
selectionBackgroundColor: string | undefined;
selectionBorderColor: string | undefined;
separatorColor: string | undefined;
scrollbarShadow: string | undefined;
scrollbarSliderBackground: string | undefined;
scrollbarSliderHoverBackground: string | undefined;
scrollbarSliderActiveBackground: string | undefined;
}
export const unthemedMenuStyles: IMenuStyles = {
shadowColor: undefined,
borderColor: undefined,
foregroundColor: undefined,
backgroundColor: undefined,
selectionForegroundColor: undefined,
selectionBackgroundColor: undefined,
selectionBorderColor: undefined,
separatorColor: undefined,
scrollbarShadow: undefined,
scrollbarSliderBackground: undefined,
scrollbarSliderHoverBackground: undefined,
scrollbarSliderActiveBackground: undefined
};
interface ISubMenuData {
parent: Menu;
submenu?: Menu;
@ -77,7 +91,7 @@ export class Menu extends ActionBar {
static globalStyleSheet: HTMLStyleElement;
protected styleSheet: HTMLStyleElement | undefined;
constructor(container: HTMLElement, actions: ReadonlyArray<IAction>, options: IMenuOptions = {}) {
constructor(container: HTMLElement, actions: ReadonlyArray<IAction>, options: IMenuOptions, private readonly menuStyles: IMenuStyles) {
container.classList.add('monaco-menu-container');
container.setAttribute('role', 'presentation');
const menuElement = document.createElement('div');
@ -101,7 +115,7 @@ export class Menu extends ActionBar {
this.menuDisposables = this._register(new DisposableStore());
this.initializeOrUpdateStyleSheet(container, {});
this.initializeOrUpdateStyleSheet(container, menuStyles);
this._register(Gesture.addTarget(menuElement));
@ -229,6 +243,8 @@ export class Menu extends ActionBar {
const scrollElement = this.scrollableElement.getDomNode();
scrollElement.style.position = '';
this.styleScrollElement(scrollElement, menuStyles);
// Support scroll on menu drag
this._register(addDisposableListener(menuElement, TouchEventType.Change, e => {
EventHelper.stop(e, true);
@ -278,30 +294,19 @@ export class Menu extends ActionBar {
this.styleSheet.textContent = getMenuWidgetCSS(style, isInShadowDOM(container));
}
style(style: IMenuStyles): void {
const container = this.getContainer();
private styleScrollElement(scrollElement: HTMLElement, style: IMenuStyles): void {
this.initializeOrUpdateStyleSheet(container, style);
const fgColor = style.foregroundColor ? `${style.foregroundColor}` : '';
const bgColor = style.backgroundColor ? `${style.backgroundColor}` : '';
const fgColor = style.foregroundColor ?? '';
const bgColor = style.backgroundColor ?? '';
const border = style.borderColor ? `1px solid ${style.borderColor}` : '';
const borderRadius = '5px';
const shadow = style.shadowColor ? `0 2px 8px ${style.shadowColor}` : '';
container.style.outline = border;
container.style.borderRadius = borderRadius;
container.style.color = fgColor;
container.style.backgroundColor = bgColor;
container.style.boxShadow = shadow;
if (this.viewItems) {
this.viewItems.forEach(item => {
if (item instanceof BaseMenuActionViewItem || item instanceof MenuSeparatorActionViewItem) {
item.style(style);
}
});
}
scrollElement.style.outline = border;
scrollElement.style.borderRadius = borderRadius;
scrollElement.style.color = fgColor;
scrollElement.style.backgroundColor = bgColor;
scrollElement.style.boxShadow = shadow;
}
override getContainer(): HTMLElement {
@ -364,9 +369,9 @@ export class Menu extends ActionBar {
private doGetActionViewItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionViewItem {
if (action instanceof Separator) {
return new MenuSeparatorActionViewItem(options.context, action, { icon: true });
return new MenuSeparatorActionViewItem(options.context, action, { icon: true }, this.menuStyles);
} else if (action instanceof SubmenuAction) {
const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.actions, parentData, { ...options, submenuIds: new Set([...(options.submenuIds || []), action.id]) });
const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.actions, parentData, { ...options, submenuIds: new Set([...(options.submenuIds || []), action.id]) }, this.menuStyles);
if (options.enableMnemonics) {
const mnemonic = menuActionViewItem.getMnemonic();
@ -396,7 +401,7 @@ export class Menu extends ActionBar {
}
}
const menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions);
const menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions, this.menuStyles);
if (options.enableMnemonics) {
const mnemonic = menuActionViewItem.getMnemonic();
@ -433,9 +438,8 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
private check: HTMLElement | undefined;
private mnemonic: string | undefined;
private cssClass: string;
protected menuStyle: IMenuStyles | undefined;
constructor(ctx: unknown, action: IAction, options: IMenuItemOptions = {}) {
constructor(ctx: unknown, action: IAction, options: IMenuItemOptions, protected readonly menuStyle: IMenuStyles) {
options.isMenu = true;
super(action, action, options);
@ -542,6 +546,8 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
this.updateTooltip();
this.updateEnabled();
this.updateChecked();
this.applyStyle();
}
override blur(): void {
@ -681,10 +687,6 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
protected applyStyle(): void {
if (!this.menuStyle) {
return;
}
const isSelected = this.element && this.element.classList.contains('focused');
const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;
const bgColor = isSelected && this.menuStyle.selectionBackgroundColor ? this.menuStyle.selectionBackgroundColor : undefined;
@ -692,21 +694,16 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
const outlineOffset = isSelected && this.menuStyle.selectionBorderColor ? `-1px` : '';
if (this.item) {
this.item.style.color = fgColor ? fgColor.toString() : '';
this.item.style.backgroundColor = bgColor ? bgColor.toString() : '';
this.item.style.color = fgColor ?? '';
this.item.style.backgroundColor = bgColor ?? '';
this.item.style.outline = outline;
this.item.style.outlineOffset = outlineOffset;
}
if (this.check) {
this.check.style.color = fgColor ? fgColor.toString() : '';
this.check.style.color = fgColor ?? '';
}
}
style(style: IMenuStyles): void {
this.menuStyle = style;
this.applyStyle();
}
}
class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
@ -723,9 +720,10 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
action: IAction,
private submenuActions: ReadonlyArray<IAction>,
private parentData: ISubMenuData,
private submenuOptions?: IMenuOptions
private submenuOptions: IMenuOptions,
menuStyles: IMenuStyles
) {
super(action, action, submenuOptions);
super(action, action, submenuOptions, menuStyles);
this.expandDirection = submenuOptions && submenuOptions.expandDirection !== undefined ? submenuOptions.expandDirection : Direction.Right;
@ -888,10 +886,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
this.submenuContainer.style.top = '0';
this.submenuContainer.style.left = '0';
this.parentData.submenu = new Menu(this.submenuContainer, this.submenuActions.length ? this.submenuActions : [new EmptySubmenuAction()], this.submenuOptions);
if (this.menuStyle) {
this.parentData.submenu.style(this.menuStyle);
}
this.parentData.submenu = new Menu(this.submenuContainer, this.submenuActions.length ? this.submenuActions : [new EmptySubmenuAction()], this.submenuOptions, this.menuStyle);
// layout submenu
const entryBox = this.element.getBoundingClientRect();
@ -951,18 +946,12 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
protected override applyStyle(): void {
super.applyStyle();
if (!this.menuStyle) {
return;
}
const isSelected = this.element && this.element.classList.contains('focused');
const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;
if (this.submenuIndicator) {
this.submenuIndicator.style.color = fgColor ? `${fgColor}` : '';
this.submenuIndicator.style.color = fgColor ?? '';
}
this.parentData.submenu?.style(this.menuStyle);
}
override dispose(): void {
@ -982,9 +971,14 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
class MenuSeparatorActionViewItem extends ActionViewItem {
style(style: IMenuStyles): void {
constructor(context: unknown, action: IAction, options: IActionViewItemOptions, private readonly menuStyles: IMenuStyles) {
super(context, action, options);
}
override render(container: HTMLElement): void {
super.render(container);
if (this.label) {
this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : '';
this.label.style.borderBottomColor = this.menuStyles.separatorColor ? `${this.menuStyles.separatorColor}` : '';
}
}
}

View file

@ -86,10 +86,9 @@ export class MenuBar extends Disposable {
private readonly _onFocusStateChange: Emitter<boolean>;
private numMenusShown: number = 0;
private menuStyle: IMenuStyles | undefined;
private overflowLayoutScheduled: IDisposable | undefined = undefined;
constructor(private container: HTMLElement, private options: IMenuBarOptions = {}) {
constructor(private container: HTMLElement, private options: IMenuBarOptions, private menuStyle: IMenuStyles) {
super();
this.container.setAttribute('role', 'menubar');
@ -608,10 +607,6 @@ export class MenuBar extends Disposable {
}
}
style(style: IMenuStyles): void {
this.menuStyle = style;
}
update(options?: IMenuBarOptions): void {
if (options) {
this.options = options;
@ -1030,10 +1025,7 @@ export class MenuBar extends Disposable {
useEventAsContext: true
};
const menuWidget = this._register(new Menu(menuHolder, customMenu.actions, menuOptions));
if (this.menuStyle) {
menuWidget.style(this.menuStyle);
}
const menuWidget = this._register(new Menu(menuHolder, customMenu.actions, menuOptions, this.menuStyle));
this._register(menuWidget.onDidCancel(() => {
this.focusState = MenubarState.FOCUSED;

View file

@ -5,16 +5,13 @@
import { IContentActionHandler } from 'vs/base/browser/formattedTextRenderer';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { IListStyles, unthemedListStyles } from 'vs/base/browser/ui/list/listWidget';
import { SelectBoxList } from 'vs/base/browser/ui/selectBox/selectBoxCustom';
import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative';
import { Widget } from 'vs/base/browser/ui/widget';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { deepClone } from 'vs/base/common/objects';
import { isMacintosh } from 'vs/base/common/platform';
import { IThemable } from 'vs/base/common/styler';
import 'vs/css!./selectBox';
@ -34,8 +31,6 @@ export interface ISelectBoxDelegate extends IDisposable {
// Delegated Widget interface
render(container: HTMLElement): void;
style(styles: ISelectBoxStyles): void;
applyStyles(): void;
}
export interface ISelectBoxOptions {
@ -58,19 +53,24 @@ export interface ISelectOptionItem {
}
export interface ISelectBoxStyles extends IListStyles {
selectBackground?: Color;
selectListBackground?: Color;
selectForeground?: Color;
decoratorRightForeground?: Color;
selectBorder?: Color;
selectListBorder?: Color;
focusBorder?: Color;
readonly selectBackground: string | undefined;
readonly selectListBackground: string | undefined;
readonly selectForeground: string | undefined;
readonly decoratorRightForeground: string | undefined;
readonly selectBorder: string | undefined;
readonly selectListBorder: string | undefined;
readonly focusBorder: string | undefined;
}
export const defaultStyles = {
selectBackground: Color.fromHex('#3C3C3C'),
selectForeground: Color.fromHex('#F0F0F0'),
selectBorder: Color.fromHex('#3C3C3C')
export const unthemedSelectBoxStyles: ISelectBoxStyles = {
...unthemedListStyles,
selectBackground: '#3C3C3C',
selectForeground: '#F0F0F0',
selectBorder: '#3C3C3C',
decoratorRightForeground: undefined,
selectListBackground: undefined,
selectListBorder: undefined,
focusBorder: undefined,
};
export interface ISelectData {
@ -78,10 +78,10 @@ export interface ISelectData {
index: number;
}
export class SelectBox extends Widget implements ISelectBoxDelegate, IThemable {
export class SelectBox extends Widget implements ISelectBoxDelegate {
private selectBoxDelegate: ISelectBoxDelegate;
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) {
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) {
super();
// Default to native SelectBox for OSX unless overridden
@ -127,12 +127,4 @@ export class SelectBox extends Widget implements ISelectBoxDelegate, IThemable {
render(container: HTMLElement): void {
this.selectBoxDelegate.render(container);
}
style(styles: ISelectBoxStyles): void {
this.selectBoxDelegate.style(styles);
}
applyStyles(): void {
this.selectBoxDelegate.applyStyles();
}
}

View file

@ -87,7 +87,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private options: ISelectOptionItem[] = [];
private selected: number;
private readonly _onDidSelect: Emitter<ISelectData>;
private styles: ISelectBoxStyles;
private readonly styles: ISelectBoxStyles;
private listRenderer!: SelectListRenderer;
private contextViewProvider!: IContextViewProvider;
private selectDropDownContainer!: HTMLElement;
@ -100,6 +100,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private _hasDetails: boolean = false;
private selectionDetailsPane!: HTMLElement;
private _skipLayout: boolean = false;
private _cachedMaxDetailsHeight?: number;
private _sticky: boolean = false; // for dev purposes only
@ -107,6 +108,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
super();
this._isVisible = false;
this.styles = styles;
this.selectBoxOptions = selectBoxOptions || Object.create(null);
if (typeof this.selectBoxOptions.minBottomMargin !== 'number') {
@ -131,8 +134,6 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this._onDidSelect = new Emitter<ISelectData>();
this._register(this._onDidSelect);
this.styles = styles;
this.registerListeners();
this.constructSelectDropDown(contextViewProvider);
@ -142,6 +143,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.setOptions(options, selected);
}
this.initStyleSheet();
}
// IDelegate - List renderer
@ -267,6 +270,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.options = options;
this.selectElement.options.length = 0;
this._hasDetails = false;
this._cachedMaxDetailsHeight = undefined;
this.options.forEach((option, index) => {
this.selectElement.add(this.createOption(option.text, index, option.isDisabled));
@ -336,15 +340,13 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.container = container;
container.classList.add('select-container');
container.appendChild(this.selectElement);
this.applyStyles();
this.styleSelectElement();
}
public style(styles: ISelectBoxStyles): void {
private initStyleSheet(): void {
const content: string[] = [];
this.styles = styles;
// Style non-native select mode
if (this.styles.listFocusBackground) {
@ -359,7 +361,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.focused) .option-decorator-right { color: ${this.styles.decoratorRightForeground}; }`);
}
if (this.styles.selectBackground && this.styles.selectBorder && !this.styles.selectBorder.equals(this.styles.selectBackground)) {
if (this.styles.selectBackground && this.styles.selectBorder && this.styles.selectBorder !== this.styles.selectBackground) {
content.push(`.monaco-select-box-dropdown-container { border: 1px solid ${this.styles.selectBorder} } `);
content.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-top { border-top: 1px solid ${this.styles.selectBorder} } `);
content.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-bottom { border-bottom: 1px solid ${this.styles.selectBorder} } `);
@ -394,43 +396,29 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: transparent !important; color: inherit !important; outline: none !important; }`);
this.styleElement.textContent = content.join('\n');
this.applyStyles();
}
public applyStyles(): void {
private styleSelectElement(): void {
const background = this.styles.selectBackground ?? '';
const foreground = this.styles.selectForeground ?? '';
const border = this.styles.selectBorder ?? '';
// Style parent select
if (this.selectElement) {
const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : '';
const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : '';
const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : '';
this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
}
// Style drop down select list (non-native mode only)
if (this.selectList) {
this.styleList();
}
this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
}
private styleList() {
if (this.selectList) {
const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : '';
this.selectList.style({});
const background = this.styles.selectBackground ?? '';
const listBackground = this.styles.selectListBackground ? this.styles.selectListBackground.toString() : background;
this.selectDropDownListContainer.style.backgroundColor = listBackground;
this.selectionDetailsPane.style.backgroundColor = listBackground;
const optionsBorder = this.styles.focusBorder ? this.styles.focusBorder.toString() : '';
this.selectDropDownContainer.style.outlineColor = optionsBorder;
this.selectDropDownContainer.style.outlineOffset = '-1px';
}
const listBackground = dom.asCssValueWithDefault(this.styles.selectListBackground, background);
this.selectDropDownListContainer.style.backgroundColor = listBackground;
this.selectionDetailsPane.style.backgroundColor = listBackground;
const optionsBorder = this.styles.focusBorder ?? '';
this.selectDropDownContainer.style.outlineColor = optionsBorder;
this.selectDropDownContainer.style.outlineOffset = '-1px';
this.selectList.style(this.styles);
}
private createOption(value: string, index: number, disabled?: boolean): HTMLOptionElement {
@ -575,7 +563,10 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.selectList.layout();
let listHeight = this.selectList.contentHeight;
const maxDetailsPaneHeight = this._hasDetails ? this.measureMaxDetailsHeight() : 0;
if (this._hasDetails && this._cachedMaxDetailsHeight === undefined) {
this._cachedMaxDetailsHeight = this.measureMaxDetailsHeight();
}
const maxDetailsPaneHeight = this._hasDetails ? this._cachedMaxDetailsHeight! : 0;
const minRequiredDropDownHeight = listHeight + verticalPadding + maxDetailsPaneHeight;
const maxVisibleOptionsBelow = ((Math.floor((maxSelectDropDownHeightBelow - verticalPadding - maxDetailsPaneHeight) / this.getHeight())));

View file

@ -168,13 +168,9 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
// Style native select
if (this.selectElement) {
const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : '';
const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : '';
const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : '';
this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
this.selectElement.style.backgroundColor = this.styles.selectBackground ?? '';
this.selectElement.style.color = this.styles.selectForeground ?? '';
this.selectElement.style.borderColor = this.styles.selectBorder ?? '';
}
}

View file

@ -29,11 +29,11 @@ export interface IPaneOptions {
}
export interface IPaneStyles {
dropBackground?: Color;
headerForeground?: Color;
headerBackground?: Color;
headerBorder?: Color;
leftBorder?: Color;
readonly dropBackground: string | undefined;
readonly headerForeground: string | undefined;
readonly headerBackground: string | undefined;
readonly headerBorder: string | undefined;
readonly leftBorder: string | undefined;
}
/**
@ -62,7 +62,13 @@ export abstract class Pane extends Disposable implements IView {
private _minimumBodySize: number;
private _maximumBodySize: number;
private _ariaHeaderLabel: string;
private styles: IPaneStyles = {};
private styles: IPaneStyles = {
dropBackground: undefined,
headerBackground: undefined,
headerBorder: undefined,
headerForeground: undefined,
leftBorder: undefined
};
private animationTimer: number | undefined = undefined;
private readonly _onDidChange = this._register(new Emitter<number | undefined>());
@ -88,9 +94,8 @@ export abstract class Pane extends Disposable implements IView {
return this.element;
}
private _dropBackground: Color | undefined;
get dropBackground(): Color | undefined {
return this._dropBackground;
get dropBackground(): string | undefined {
return this.styles.dropBackground;
}
get minimumBodySize(): number {
@ -299,10 +304,9 @@ export abstract class Pane extends Disposable implements IView {
this.header.classList.toggle('expanded', expanded);
this.header.setAttribute('aria-expanded', String(expanded));
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.color = this.styles.headerForeground ?? '';
this.header.style.backgroundColor = this.styles.headerBackground ?? '';
this.header.style.borderTop = this.styles.headerBorder && this.orientation === Orientation.VERTICAL ? `1px solid ${this.styles.headerBorder}` : '';
this._dropBackground = this.styles.dropBackground;
this.element.style.borderLeft = this.styles.leftBorder && this.orientation === Orientation.HORIZONTAL ? `1px solid ${this.styles.leftBorder}` : '';
}
@ -416,7 +420,7 @@ class PaneDraggable extends Disposable {
let backgroundColor: string | null = null;
if (this.dragOverCounter > 0) {
backgroundColor = (this.pane.dropBackground || PaneDraggable.DefaultDragOverBackgroundColor).toString();
backgroundColor = this.pane.dropBackground ?? PaneDraggable.DefaultDragOverBackgroundColor.toString();
}
this.pane.dropTargetElement.style.backgroundColor = backgroundColor || '';

View file

@ -5,14 +5,13 @@
import { $, append, clearNode, createStyleSheet, getContentHeight, getContentWidth } from 'vs/base/browser/dom';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IListOptions, IListOptionsUpdate, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';
import { IListOptions, IListOptionsUpdate, IListStyles, List, unthemedListStyles } from 'vs/base/browser/ui/list/listWidget';
import { ISplitViewDescriptor, IView, Orientation, SplitView } from 'vs/base/browser/ui/splitview/splitview';
import { ITableColumn, ITableContextMenuEvent, ITableEvent, ITableGestureEvent, ITableMouseEvent, ITableRenderer, ITableTouchEvent, ITableVirtualDelegate } from 'vs/base/browser/ui/table/table';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { ISpliceable } from 'vs/base/common/sequence';
import { IThemable } from 'vs/base/common/styler';
import 'vs/css!./table';
// TODO@joao
@ -140,7 +139,7 @@ export interface ITableOptions<TRow> extends IListOptions<TRow> { }
export interface ITableOptionsUpdate extends IListOptionsUpdate { }
export interface ITableStyles extends IListStyles { }
export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
export class Table<TRow> implements ISpliceable<TRow>, IDisposable {
private static InstanceCount = 0;
readonly domId = `table_id_${++Table.InstanceCount}`;
@ -221,7 +220,7 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
}, null, this.disposables);
this.styleElement = createStyleSheet(this.domNode);
this.style({});
this.style(unthemedListStyles);
}
updateOptions(options: ITableOptionsUpdate): void {

View file

@ -66,7 +66,7 @@ export class ToolBar extends Disposable {
ariaLabel: options.ariaLabel,
actionRunner: options.actionRunner,
allowContextMenu: options.allowContextMenu,
actionViewItemProvider: (action: IAction) => {
actionViewItemProvider: (action, viewItemOptions) => {
if (action.id === ToggleMenuAction.ID) {
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
action,
@ -88,7 +88,7 @@ export class ToolBar extends Disposable {
}
if (options.actionViewItemProvider) {
const result = options.actionViewItemProvider(action);
const result = options.actionViewItemProvider(action, viewItemOptions);
if (result) {
return result;

View file

@ -1770,7 +1770,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
const content: string[] = [];
if (styles.treeIndentGuidesStroke) {
content.push(`.monaco-list${suffix}:hover .monaco-tl-indent > .indent-guide, .monaco-list${suffix}.always .monaco-tl-indent > .indent-guide { border-color: ${styles.treeIndentGuidesStroke.transparent(0.4)}; }`);
content.push(`.monaco-list${suffix}:hover .monaco-tl-indent > .indent-guide, .monaco-list${suffix}.always .monaco-tl-indent > .indent-guide { border-color: ${styles.treeInactiveIndentGuidesStroke}; }`);
content.push(`.monaco-list${suffix} .monaco-tl-indent > .indent-guide.active { border-color: ${styles.treeIndentGuidesStroke}; }`);
}

View file

@ -20,7 +20,6 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Iterable } from 'vs/base/common/iterator';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { IThemable } from 'vs/base/common/styler';
import { isIterable } from 'vs/base/common/types';
interface IAsyncDataTreeNode<TInput, T> {
@ -312,7 +311,7 @@ function dfs<TInput, T>(node: IAsyncDataTreeNode<TInput, T>, fn: (node: IAsyncDa
node.children.forEach(child => dfs(child, fn));
}
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable, IThemable {
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable {
protected readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected readonly root: IAsyncDataTreeNode<TInput, T>;
@ -347,6 +346,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidBlur(): Event<void> { return this.tree.onDidBlur; }
/**
* To be used internally only!
* @deprecated
*/
get onDidChangeModel(): Event<void> { return this.tree.onDidChangeModel; }
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<IAsyncDataTreeNode<TInput, T> | null, TFilterData>> { return this.tree.onDidChangeCollapseState; }

View file

@ -6,7 +6,8 @@
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { ICollapseStateChangeEvent, ITreeElement, ITreeFilter, ITreeFilterDataResult, ITreeModel, ITreeModelSpliceEvent, ITreeNode, TreeError, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
import { splice, tail2 } from 'vs/base/common/arrays';
import { Delayer, MicrotaskDelay } from 'vs/base/common/async';
import { Delayer } from 'vs/base/common/async';
import { MicrotaskDelay } from 'vs/base/common/symbols';
import { LcsDiff } from 'vs/base/common/diff/diff';
import { Emitter, Event, EventBufferer } from 'vs/base/common/event';
import { Iterable } from 'vs/base/common/iterator';

View file

@ -14,10 +14,10 @@ export interface ITelemetryData {
}
export type WorkbenchActionExecutedClassification = {
owner: 'bpasero';
comment: 'TODO @bpasero';
id: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The identifier of the action that was run.' };
from: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the component the action was run from.' };
owner: 'bpasero';
comment: 'Provides insight into actions that are executed within the workbench.';
};
export type WorkbenchActionExecutedEvent = {

View file

@ -10,6 +10,7 @@ import { Disposable, IDisposable, MutableDisposable, toDisposable } from 'vs/bas
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { setTimeout0 } from 'vs/base/common/platform';
import { MicrotaskDelay } from './symbols';
export function isThenable<T>(obj: unknown): obj is Promise<T> {
return !!obj && typeof (obj as unknown as Promise<T>).then === 'function';
@ -274,9 +275,6 @@ const microtaskDeferred = (fn: () => void): IScheduledLater => {
};
};
/** Can be passed into the Delayed to defer using a microtask */
export const MicrotaskDelay = Symbol('MicrotaskDelay');
/**
* A helper to delay (debounce) execution of a task that is being requested often.
*

View file

@ -2,20 +2,9 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ThemeIcon } from 'vs/base/common/themables';
import { isString } from 'vs/base/common/types';
// Selects all codicon names encapsulated in the `$()` syntax and wraps the
// results with spaces so that screen readers can read the text better.
export function getCodiconAriaLabel(text: string | undefined) {
if (!text) {
return '';
}
return text.replace(/\$\((.*?)\)/g, (_match, codiconName) => ` ${codiconName} `).trim();
}
const _codiconFontCharacters: { [id: string]: number } = Object.create(null);
function register(id: string, fontCharacter: number | string): ThemeIcon {
@ -307,6 +296,7 @@ export const Codicon = {
italic: register('italic', 0xeb0d),
jersey: register('jersey', 0xeb0e),
json: register('json', 0xeb0f),
bracket: register('bracket', 0xeb0f),
kebabVertical: register('kebab-vertical', 0xeb10),
key: register('key', 0xeb11),
law: register('law', 0xeb12),
@ -529,7 +519,6 @@ export const Codicon = {
graphLine: register('graph-line', 0xebe2),
graphScatter: register('graph-scatter', 0xebe3),
pieChart: register('pie-chart', 0xebe4),
bracket: register('bracket', 0xebe4),
bracketDot: register('bracket-dot', 0xebe5),
bracketError: register('bracket-error', 0xebe6),
lockSmall: register('lock-small', 0xebe7),

View file

@ -78,6 +78,16 @@ export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) =>
errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler);
}
/**
* Returns if the error is a SIGPIPE error. SIGPIPE errors should generally be
* logged at most once, to avoid a loop.
*
* @see https://github.com/microsoft/vscode-remote-release/issues/6481
*/
export function isSigPipeError(e: unknown): e is Error {
return !!e && typeof e === 'object' && (<any>e).code === 'EPIPE' && (<any>e).syscall === 'WRITE';
}
export function onUnexpectedError(e: any): undefined {
// ignore errors from cancelled promises
if (!isCancellationError(e)) {

View file

@ -10,6 +10,7 @@ import { combinedDisposable, Disposable, DisposableStore, IDisposable, SafeDispo
import { LinkedList } from 'vs/base/common/linkedList';
import { IObservable, IObserver } from 'vs/base/common/observable';
import { StopWatch } from 'vs/base/common/stopwatch';
import { MicrotaskDelay } from 'vs/base/common/symbols';
// -----------------------------------------------------------------------------------------------------------------------
@ -197,15 +198,15 @@ export namespace Event {
* event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
* returned event causes this utility to leak a listener on the original event.
*/
export function debounce<T>(event: Event<T>, merge: (last: T | undefined, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<T>;
export function debounce<T>(event: Event<T>, merge: (last: T | undefined, event: T) => T, delay?: number | typeof MicrotaskDelay, leading?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<T>;
/**
* *NOTE* that this function returns an `Event` and it MUST be called with a `DisposableStore` whenever the returned
* event is accessible to "third parties", e.g the event is a public property. Otherwise a leaked listener on the
* returned event causes this utility to leak a listener on the original event.
*/
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O>;
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay?: number | typeof MicrotaskDelay, leading?: boolean, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O>;
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay: number = 100, leading = false, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O> {
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay: number | typeof MicrotaskDelay = 100, leading = false, leakWarningThreshold?: number, disposable?: DisposableStore): Event<O> {
let subscription: IDisposable;
let output: O | undefined = undefined;
@ -224,17 +225,25 @@ export namespace Event {
output = undefined;
}
clearTimeout(handle);
handle = setTimeout(() => {
const doFire = () => {
const _output = output;
output = undefined;
handle = undefined;
if (!leading || numDebouncedCalls > 1) {
emitter.fire(_output!);
}
numDebouncedCalls = 0;
}, delay);
};
if (typeof delay === 'number') {
clearTimeout(handle);
handle = setTimeout(doFire, delay);
} else {
if (handle === undefined) {
handle = 0;
queueMicrotask(doFire);
}
}
});
},
onDidRemoveLastListener() {

View file

@ -23,6 +23,10 @@ export function markdownEscapeEscapedIcons(text: string): string {
}
const stripIconsRegex = new RegExp(`(\\s)?(\\\\)?${iconsRegex.source}(\\s)?`, 'g');
/**
* Takes a label with icons (`$(iconId)xyz`) and strips the icons out (`xyz`)
*/
export function stripIcons(text: string): string {
if (text.indexOf(iconStartMarker) === -1) {
return text;
@ -32,6 +36,18 @@ export function stripIcons(text: string): string {
}
/**
* Takes a label with icons (`$(iconId)xyz`), removes the icon syntax adds whitespace so that screen readers can read the text better.
*/
export function getCodiconAriaLabel(text: string | undefined) {
if (!text) {
return '';
}
return text.replace(/\$\((.*?)\)/g, (_match, codiconName) => ` ${codiconName} `).trim();
}
export interface IParsedLabelWithIcons {
readonly text: string;
readonly iconOffsets?: readonly number[];
@ -39,6 +55,9 @@ export interface IParsedLabelWithIcons {
const _parseIconsRegex = new RegExp(`\\$\\(${ThemeIcon.iconNameCharacter}+\\)`, 'g');
/**
* Takes a label with icons (`abc $(iconId)xyz`) and returns the text (`abc xyz`) and the offsets of the icons (`[3]`)
*/
export function parseLabelWithIcons(input: string): IParsedLabelWithIcons {
_parseIconsRegex.lastIndex = 0;

View file

@ -108,7 +108,7 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve
}, {} as Record<string, boolean>);
const keysToRemove = [
/^ELECTRON_.+$/,
/^VSCODE_(?!SHELL_LOGIN).+$/,
/^VSCODE_(?!(PORTABLE|SHELL_LOGIN)).+$/,
/^SNAP(|_.*)$/,
/^GDK_PIXBUF_.+$/,
];

View file

@ -91,6 +91,8 @@ export interface IProductConfiguration {
readonly trustedExtensionUrlPublicKeys?: { [id: string]: string[] };
readonly trustedExtensionAuthAccess?: readonly string[];
readonly commandPaletteSuggestedCommandIds?: string[];
readonly crashReporter?: {
readonly companyName: string;
readonly productName: string;

View file

@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Can be passed into the Delayed to defer using a microtask
* */
export const MicrotaskDelay = Symbol('MicrotaskDelay');

View file

@ -237,7 +237,7 @@
vertical-align: text-bottom;
}
.quick-input-list .quick-input-list-rows .monaco-highlighted-label > * {
.quick-input-list .quick-input-list-rows .monaco-highlighted-label > span {
opacity: 1;
}

View file

@ -22,7 +22,6 @@ import { TimeoutTimer } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Codicon } from 'vs/base/common/codicons';
import { ThemeIcon } from 'vs/base/common/themables';
import { Color } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
@ -55,22 +54,23 @@ export interface IQuickInputOptions {
}
export interface IQuickInputStyles {
widget: IQuickInputWidgetStyles;
inputBox: IInputBoxStyles;
toggle: IToggleStyles;
countBadge: ICountBadgeStyles;
button: IButtonStyles;
progressBar: IProgressBarStyles;
keybindingLabel: IKeybindingLabelStyles;
list: IListStyles & { pickerGroupBorder?: Color; pickerGroupForeground?: Color };
readonly widget: IQuickInputWidgetStyles;
readonly inputBox: IInputBoxStyles;
readonly toggle: IToggleStyles;
readonly countBadge: ICountBadgeStyles;
readonly button: IButtonStyles;
readonly progressBar: IProgressBarStyles;
readonly keybindingLabel: IKeybindingLabelStyles;
readonly list: IListStyles;
readonly pickerGroup: { pickerGroupBorder: string | undefined; pickerGroupForeground: string | undefined };
}
export interface IQuickInputWidgetStyles {
quickInputBackground?: Color;
quickInputForeground?: Color;
quickInputTitleBackground?: Color;
widgetBorder?: Color;
widgetShadow?: Color;
readonly quickInputBackground: string | undefined;
readonly quickInputForeground: string | undefined;
readonly quickInputTitleBackground: string | undefined;
readonly widgetBorder: string | undefined;
readonly widgetShadow: string | undefined;
}
const $ = dom.$;
@ -1835,22 +1835,22 @@ export class QuickInputController extends Disposable {
widgetBorder,
widgetShadow,
} = this.styles.widget;
this.ui.titleBar.style.backgroundColor = quickInputTitleBackground ? quickInputTitleBackground.toString() : '';
this.ui.container.style.backgroundColor = quickInputBackground ? quickInputBackground.toString() : '';
this.ui.container.style.color = quickInputForeground ? quickInputForeground.toString() : '';
this.ui.titleBar.style.backgroundColor = quickInputTitleBackground ?? '';
this.ui.container.style.backgroundColor = quickInputBackground ?? '';
this.ui.container.style.color = quickInputForeground ?? '';
this.ui.container.style.border = widgetBorder ? `1px solid ${widgetBorder}` : '';
this.ui.container.style.boxShadow = widgetShadow ? `0 0 8px 2px ${widgetShadow}` : '';
this.ui.list.style(this.styles.list);
const content: string[] = [];
if (this.styles.list.pickerGroupBorder) {
content.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.list.pickerGroupBorder}; }`);
if (this.styles.pickerGroup.pickerGroupBorder) {
content.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.pickerGroup.pickerGroupBorder}; }`);
}
if (this.styles.list.pickerGroupForeground) {
content.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.list.pickerGroupForeground}; }`);
if (this.styles.pickerGroup.pickerGroupForeground) {
content.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.pickerGroup.pickerGroupForeground}; }`);
}
if (this.styles.list.pickerGroupForeground) {
content.push(`.quick-input-list .quick-input-list-separator-as-item { color: ${this.styles.list.pickerGroupForeground}; }`);
if (this.styles.pickerGroup.pickerGroupForeground) {
content.push(`.quick-input-list .quick-input-list-separator-as-item { color: ${this.styles.pickerGroup.pickerGroupForeground}; }`);
}
if (

View file

@ -13,12 +13,11 @@ import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/lis
import { IListAccessibilityProvider, IListOptions, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';
import { IAction } from 'vs/base/common/actions';
import { range } from 'vs/base/common/arrays';
import { getCodiconAriaLabel } from 'vs/base/common/codicons';
import { compareAnything } from 'vs/base/common/comparers';
import { memoize } from 'vs/base/common/decorators';
import { Emitter, Event } from 'vs/base/common/event';
import { IMatch } from 'vs/base/common/filters';
import { IParsedLabelWithIcons, matchesFuzzyIconAware, parseLabelWithIcons } from 'vs/base/common/iconLabels';
import { getCodiconAriaLabel, IParsedLabelWithIcons, matchesFuzzyIconAware, parseLabelWithIcons } from 'vs/base/common/iconLabels';
import { KeyCode } from 'vs/base/common/keyCodes';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';

View file

@ -7,7 +7,7 @@ import * as assert from 'assert';
import { unthemedInboxStyles } from 'vs/base/browser/ui/inputbox/inputBox';
import { unthemedButtonStyles } from 'vs/base/browser/ui/button/button';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IListOptions, List } from 'vs/base/browser/ui/list/listWidget';
import { IListOptions, List, unthemedListStyles } from 'vs/base/browser/ui/list/listWidget';
import { unthemedToggleStyles } from 'vs/base/browser/ui/toggle/toggle';
import { raceTimeout } from 'vs/base/common/async';
import { QuickInputController } from 'vs/base/parts/quickinput/browser/quickInput';
@ -61,9 +61,19 @@ suite('QuickInput', () => { // https://github.com/microsoft/vscode/issues/147543
inputBox: unthemedInboxStyles,
toggle: unthemedToggleStyles,
keybindingLabel: {},
list: {},
list: unthemedListStyles,
progressBar: {},
widget: {}
widget: {
quickInputBackground: undefined,
quickInputForeground: undefined,
quickInputTitleBackground: undefined,
widgetBorder: undefined,
widgetShadow: undefined,
},
pickerGroup: {
pickerGroupBorder: undefined,
pickerGroupForeground: undefined,
},
}
});

View file

@ -5,6 +5,7 @@
import * as assert from 'assert';
import { $ } from 'vs/base/browser/dom';
import { unthemedMenuStyles } from 'vs/base/browser/ui/menu/menu';
import { MenuBar } from 'vs/base/browser/ui/menu/menubar';
function getButtonElementByAriaLabel(menubarElement: HTMLElement, ariaLabel: string): HTMLElement | null {
@ -65,7 +66,7 @@ suite('Menubar', () => {
const menubar = new MenuBar(container, {
enableMnemonics: true,
visibility: 'visible'
});
}, unthemedMenuStyles);
test('English File menu renders mnemonics', function () {
validateMenuBarItem(menubar, container, '&File', 'File', 'F');

View file

@ -5,6 +5,7 @@
import * as assert from 'assert';
import * as async from 'vs/base/common/async';
import * as MicrotaskDelay from "vs/base/common/symbols";
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { isCancellationError } from 'vs/base/common/errors';
import { Event } from 'vs/base/common/event';
@ -188,7 +189,7 @@ suite('Async', () => {
return Promise.resolve(++count);
};
const delayer = new async.Delayer(async.MicrotaskDelay);
const delayer = new async.Delayer(MicrotaskDelay.MicrotaskDelay);
const promises: Promise<any>[] = [];
assert(!delayer.isTriggered());
@ -251,7 +252,7 @@ suite('Async', () => {
return Promise.resolve(++count);
};
const delayer = new async.Delayer(async.MicrotaskDelay);
const delayer = new async.Delayer(MicrotaskDelay.MicrotaskDelay);
assert(!delayer.isTriggered());

View file

@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { getCodiconAriaLabel } from 'vs/base/common/codicons';
suite('Codicon', () => {
test('Can get proper aria labels', () => {
// note, the spaces in the results are important
const testCases = new Map<string, string>([
['', ''],
['asdf', 'asdf'],
['asdf$(squirrel)asdf', 'asdf squirrel asdf'],
['asdf $(squirrel) asdf', 'asdf squirrel asdf'],
['$(rocket)asdf', 'rocket asdf'],
['$(rocket) asdf', 'rocket asdf'],
['$(rocket)$(rocket)$(rocket)asdf', 'rocket rocket rocket asdf'],
['$(rocket) asdf $(rocket)', 'rocket asdf rocket'],
['$(rocket)asdf$(rocket)', 'rocket asdf rocket'],
]);
for (const [input, expected] of testCases) {
assert.strictEqual(getCodiconAriaLabel(input), expected);
}
});
});

View file

@ -9,6 +9,7 @@ import { errorHandler, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { AsyncEmitter, DebounceEmitter, Emitter, Event, EventBufferer, EventMultiplexer, IWaitUntil, MicrotaskEmitter, PauseableEmitter, Relay } from 'vs/base/common/event';
import { DisposableStore, IDisposable, isDisposable, setDisposableTracker, toDisposable } from 'vs/base/common/lifecycle';
import { observableValue, transaction } from 'vs/base/common/observable';
import { MicrotaskDelay } from 'vs/base/common/symbols';
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { DisposableTracker, ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
@ -270,6 +271,39 @@ suite('Event', function () {
doc.setText('3');
});
test('Debounce Event (microtask)', function (done: () => void) {
const doc = new Samples.Document3();
const onDocDidChange = Event.debounce(doc.onDidChange, (prev: string[] | undefined, cur) => {
if (!prev) {
prev = [cur];
} else if (prev.indexOf(cur) < 0) {
prev.push(cur);
}
return prev;
}, MicrotaskDelay);
let count = 0;
onDocDidChange(keys => {
count++;
assert.ok(keys, 'was not expecting keys.');
if (count === 1) {
doc.setText('4');
assert.deepStrictEqual(keys, ['1', '2', '3']);
} else if (count === 2) {
assert.deepStrictEqual(keys, ['4']);
done();
}
});
doc.setText('1');
doc.setText('2');
doc.setText('3');
});
test('Debounce Event - leading', async function () {
const emitter = new Emitter<void>();
const debounced = Event.debounce(emitter.event, (l, e) => e, 0, /*leading=*/true);
@ -286,7 +320,7 @@ suite('Event', function () {
assert.strictEqual(calls, 1);
});
test('Debounce Event - leading', async function () {
test('Debounce Event - leading (2)', async function () {
const emitter = new Emitter<void>();
const debounced = Event.debounce(emitter.event, (l, e) => e, 0, /*leading=*/true);

View file

@ -5,7 +5,7 @@
import * as assert from 'assert';
import { IMatch } from 'vs/base/common/filters';
import { escapeIcons, IParsedLabelWithIcons, markdownEscapeEscapedIcons, matchesFuzzyIconAware, parseLabelWithIcons, stripIcons } from 'vs/base/common/iconLabels';
import { escapeIcons, getCodiconAriaLabel, IParsedLabelWithIcons, markdownEscapeEscapedIcons, matchesFuzzyIconAware, parseLabelWithIcons, stripIcons } from 'vs/base/common/iconLabels';
interface IIconFilter {
// Returns null if word doesn't match.
@ -21,6 +21,26 @@ function filterOk(filter: IIconFilter, word: string, target: IParsedLabelWithIco
}
suite('Icon Labels', () => {
test('Can get proper aria labels', () => {
// note, the spaces in the results are important
const testCases = new Map<string, string>([
['', ''],
['asdf', 'asdf'],
['asdf$(squirrel)asdf', 'asdf squirrel asdf'],
['asdf $(squirrel) asdf', 'asdf squirrel asdf'],
['$(rocket)asdf', 'rocket asdf'],
['$(rocket) asdf', 'rocket asdf'],
['$(rocket)$(rocket)$(rocket)asdf', 'rocket rocket rocket asdf'],
['$(rocket) asdf $(rocket)', 'rocket asdf rocket'],
['$(rocket)asdf$(rocket)', 'rocket asdf rocket'],
]);
for (const [input, expected] of testCases) {
assert.strictEqual(getCodiconAriaLabel(input), expected);
}
});
test('matchesFuzzyIconAware', () => {
// Camel Case

View file

@ -19,7 +19,7 @@ suite('Processes', () => {
VSCODE_DEV: 'x',
VSCODE_IPC_HOOK: 'x',
VSCODE_NLS_CONFIG: 'x',
VSCODE_PORTABLE: 'x',
VSCODE_PORTABLE: '3',
VSCODE_PID: 'x',
VSCODE_SHELL_LOGIN: '1',
VSCODE_CODE_CACHE_PATH: 'x',
@ -30,6 +30,7 @@ suite('Processes', () => {
processes.sanitizeProcessEnvironment(env);
assert.strictEqual(env['FOO'], 'bar');
assert.strictEqual(env['VSCODE_SHELL_LOGIN'], '1');
assert.strictEqual(Object.keys(env).length, 2);
assert.strictEqual(env['VSCODE_PORTABLE'], '3');
assert.strictEqual(Object.keys(env).length, 3);
});
});

View file

@ -217,7 +217,7 @@ class SharedProcessMain extends Disposable {
services.set(INativeEnvironmentService, environmentService);
// Logger
const loggerService = new LoggerChannelClient(undefined, this.configuration.logLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
const loggerService = new LoggerChannelClient(undefined, this.configuration.logLevel, this.configuration.loggers.map(loggerResource => ({ ...loggerResource, resource: URI.revive(loggerResource.resource) })), mainProcessService.getChannel('logger'));
services.set(ILoggerService, loggerService);
// Log

View file

@ -1257,9 +1257,9 @@ export class CodeApplication extends Disposable {
// Telemetry
type SharedProcessErrorClassification = {
type: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The type of shared process crash to understand the nature of the crash better.' };
reason: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The type of shared process crash to understand the nature of the crash better.' };
code: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The type of shared process crash to understand the nature of the crash better.' };
visible: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether shared process window was visible or not.' };
reason: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The reason of the shared process crash to understand the nature of the crash better.' };
code: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The exit code of the shared process crash to understand the nature of the crash better.' };
visible: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether the shared process window was visible or not.' };
shuttingdown: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether the application is shutting down when the crash happens.' };
owner: 'bpasero';
comment: 'Event which fires whenever an error occurs in the shared process';

View file

@ -67,7 +67,6 @@ import { FilePolicyService } from 'vs/platform/policy/common/filePolicyService';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { PROFILES_ENABLEMENT_CONFIG } from 'vs/platform/userDataProfile/common/userDataProfile';
import { ILoggerMainService, LoggerMainService } from 'vs/platform/log/electron-main/loggerService';
import { LogService } from 'vs/platform/log/common/logService';
@ -258,7 +257,8 @@ class CodeMain {
configurationService.initialize()
]);
userDataProfilesMainService.setEnablement(productService.quality !== 'stable' || configurationService.getValue(PROFILES_ENABLEMENT_CONFIG));
// Initialize user data profiles after initializing the state
userDataProfilesMainService.init();
}
private async claimInstance(logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {

View file

@ -7,7 +7,7 @@ import { hostname, release } from 'os';
import { raceTimeout } from 'vs/base/common/async';
import { VSBuffer } from 'vs/base/common/buffer';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { isSigPipeError, onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { isAbsolute, join } from 'vs/base/common/path';
@ -58,7 +58,7 @@ import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
import { buildTelemetryMessage } from 'vs/platform/telemetry/node/telemetry';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { IUserDataProfilesService, PROFILES_ENABLEMENT_CONFIG } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { UserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile';
import { resolveMachineId } from 'vs/platform/telemetry/node/telemetryUtils';
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
@ -171,7 +171,8 @@ class CliMain extends Disposable {
configurationService.initialize()
]);
userDataProfilesService.setEnablement(productService.quality !== 'stable' || configurationService.getValue(PROFILES_ENABLEMENT_CONFIG));
// Initialize user data profiles after initializing the state
userDataProfilesService.init();
// URI Identity
services.set(IUriIdentityService, new UriIdentityService(fileService));
@ -242,12 +243,23 @@ class CliMain extends Disposable {
});
// Handle unhandled errors that can occur
process.on('uncaughtException', err => onUnexpectedError(err));
process.on('uncaughtException', err => {
if (!isSigPipeError(err)) {
onUnexpectedError(err);
}
});
process.on('unhandledRejection', (reason: unknown) => onUnexpectedError(reason));
}
private async doRun(environmentService: INativeEnvironmentService, fileService: IFileService, userDataProfilesService: IUserDataProfilesService, instantiationService: IInstantiationService): Promise<void> {
const profileLocation = (environmentService.args.profile ? userDataProfilesService.profiles.find(p => p.name === environmentService.args.profile) ?? userDataProfilesService.defaultProfile : userDataProfilesService.defaultProfile).extensionsResource;
let profile: IUserDataProfile | undefined = undefined;
if (environmentService.args.profile) {
profile = userDataProfilesService.profiles.find(p => p.name === environmentService.args.profile);
if (!profile) {
throw new Error(`Profile '${environmentService.args.profile}' not found.`);
}
}
const profileLocation = (profile ?? userDataProfilesService.defaultProfile).extensionsResource;
// Install Source
if (this.argv['install-source']) {

View file

@ -9,7 +9,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { asCssValue } from 'vs/platform/theme/common/colorRegistry';
import { asCssVariable } from 'vs/platform/theme/common/colorRegistry';
import { ThemeColor } from 'vs/base/common/themables';
/**
@ -378,7 +378,7 @@ class RefCountedCssRule {
const value = (properties as any)[prop] as string | ThemeColor;
let cssValue;
if (typeof value === 'object') {
cssValue = asCssValue(value.id);
cssValue = asCssVariable(value.id);
} else {
cssValue = value;
}

View file

@ -231,18 +231,15 @@ export class DiffNavigator extends Disposable implements IDiffNavigator {
}
const insertedOrModified = modifiedEditor.getLineDecorations(lineNumber).find(l => l.options.className === 'line-insert');
if (insertedOrModified) {
this._audioCueService.playAudioCue(AudioCue.diffLineModified);
this._audioCueService.playAudioCue(AudioCue.diffLineModified, true);
} else if (jumpToChange) {
// The modified editor does not include deleted lines, but when
// we are moved to the area where lines were deleted, play this cue
this._audioCueService.playAudioCue(AudioCue.diffLineDeleted);
this._audioCueService.playAudioCue(AudioCue.diffLineDeleted, true);
} else {
return;
}
if (!jumpToChange || !insertedOrModified) {
return;
}
const codeEditor = this._codeEditorService.getActiveCodeEditor();
if (codeEditor && insertedOrModified && this._accessibilityService.isScreenReaderOptimized()) {
codeEditor.setSelection({ startLineNumber: lineNumber, startColumn: 0, endLineNumber: lineNumber, endColumn: Number.MAX_VALUE });

Some files were not shown because too many files have changed in this diff Show more