mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 21:55:38 +00:00
Merge remote-tracking branch 'origin/main' into connor4312/cli-wsl-control-2
This commit is contained in:
commit
c600c10579
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -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.
|
||||
|
|
|
@ -1 +1 @@
|
|||
2022-08-01T11:24:47.411Z
|
||||
2023-01-19T08:04:33.652Z
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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=
|
|
@ -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
4
cli/Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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'),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
29
extensions/configuration-editing/src/node/net.ts
Normal file
29
extensions/configuration-editing/src/node/net.ts
Normal 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;
|
||||
}
|
||||
}
|
6
extensions/configuration-editing/src/typings/ref.d.ts
vendored
Normal file
6
extensions/configuration-editing/src/typings/ref.d.ts
vendored
Normal 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';
|
|
@ -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",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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==
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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();
|
|
@ -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"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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": [
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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();
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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();
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
16
package.json
16
package.json
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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==
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
10
src/bootstrap.js
vendored
|
@ -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`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
19
src/main.js
19
src/main.js
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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}` : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())));
|
||||
|
|
|
@ -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 ?? '';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 || '';
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}; }`);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_.+$/,
|
||||
];
|
||||
|
|
|
@ -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;
|
||||
|
|
9
src/vs/base/common/symbols.ts
Normal file
9
src/vs/base/common/symbols.ts
Normal 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');
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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']) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue