Merge from vscode 7eaf220cafb9d9e901370ffce02229171cbf3ea6

This commit is contained in:
ADS Merger
2020-09-03 02:34:56 +00:00
committed by Anthony Dresser
parent 39d9eed585
commit a63578e6f7
519 changed files with 14338 additions and 6670 deletions

View File

@@ -682,6 +682,20 @@
"**/{vs,sql}/workbench/services/**/{common,browser}/**"
]
},
{
"target": "**/{vs,sql}/workbench/contrib/notebook/common/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,worker}/**",
"**/vs/platform/**/common/**",
"**/vs/editor/**",
"**/vs/workbench/common/**",
"**/vs/workbench/api/common/**",
"**/vs/workbench/services/**/common/**",
"**/vs/workbench/contrib/**/common/**"
]
},
{
"target": "**/{vs,sql}/workbench/contrib/**/common/**",
"restrictions": [

3
.vscode/launch.json vendored
View File

@@ -19,7 +19,8 @@
"timeout": 30000,
"port": 5870,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
"${workspaceFolder}/out/**/*.js",
"${workspaceFolder}/extensions/*/out/**/*.js"
]
},
{

16
.vscode/tasks.json vendored
View File

@@ -139,7 +139,7 @@
"label": "Kill Build Web Extensions",
"group": "build",
"presentation": {
"reveal": "never",
"reveal": "never"
},
"problemMatcher": "$tsc"
},
@@ -209,5 +209,19 @@
"reveal": "silent"
}
},
{
"type": "npm",
"script": "tsec-compile-check",
"problemMatcher": [
{
"base": "$tsc",
"applyTo": "allDocuments",
"owner": "tsec"
},
],
"group": "build",
"label": "npm: tsec-compile-check",
"detail": "node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit"
}
]
}

View File

@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron"
target "9.2.0"
target "9.2.1"
runtime "electron"

View File

@@ -42,6 +42,7 @@ const vscodeEntryPoints = _.flatten([
buildfile.entrypoint('vs/workbench/workbench.desktop.main'),
buildfile.base,
buildfile.workerExtensionHost,
buildfile.workerNotebook,
buildfile.workbenchDesktop,
buildfile.code
]);

View File

@@ -53,7 +53,9 @@ function createAsar(folderPath, unpackGlobs, destFilename) {
const insertFile = (relativePath, stat, shouldUnpack) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
// Do not pass `onFileInserted` directly because it gets overwritten below.
// Create a closure capturing `onFileInserted`.
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted());
};
return es.through(function (file) {
if (file.stat.isDirectory()) {

View File

@@ -8,10 +8,17 @@
import * as path from 'path';
import * as es from 'event-stream';
const pickle = require('chromium-pickle-js');
const Filesystem = require('asar/lib/filesystem');
const Filesystem = <typeof AsarFilesystem>require('asar/lib/filesystem');
import * as VinylFile from 'vinyl';
import * as minimatch from 'minimatch';
declare class AsarFilesystem {
readonly header: unknown;
constructor(src: string);
insertDirectory(path: string, shouldUnpack?: boolean): unknown;
insertFile(path: string, shouldUnpack: boolean, file: { stat: { size: number; mode: number; }; }, options: {}): Promise<void>;
}
export function createAsar(folderPath: string, unpackGlobs: string[], destFilename: string): NodeJS.ReadWriteStream {
const shouldUnpackFile = (file: VinylFile): boolean => {
@@ -61,7 +68,9 @@ export function createAsar(folderPath: string, unpackGlobs: string[], destFilena
const insertFile = (relativePath: string, stat: { size: number; mode: number; }, shouldUnpack: boolean) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
// Do not pass `onFileInserted` directly because it gets overwritten below.
// Create a closure capturing `onFileInserted`.
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted());
};
return es.through(function (file) {

View File

@@ -50,7 +50,7 @@
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"terser": "4.3.8",
"typescript": "^4.0.1-rc",
"typescript": "^4.1.0-dev.20200824",
"vsce": "1.48.0",
"vscode-telemetry-extractor": "^1.6.0",
"xml2js": "^0.4.17"

View File

@@ -3544,10 +3544,10 @@ typescript@^3.0.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
typescript@^4.0.1-rc:
version "4.0.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.1-rc.tgz#8adc78223eae56fe71d906a5fa90c3543b07a677"
integrity sha512-TCkspT3dSKOykbzS3/WSK7pqU2h1d/lEO6i45Afm5Y3XNAEAo8YXTG3kHOQk/wFq/5uPyO1+X8rb/Q+g7UsxJw==
typescript@^4.1.0-dev.20200824:
version "4.1.0-dev.20200824"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.0-dev.20200824.tgz#34c92d9b6e5124600658c0d4e9b8c125beaf577d"
integrity sha512-hTJfocmebnMKoqRw/xs3bL61z87XXtvOUwYtM7zaCX9mAvnfdo1x1bzQlLZAsvdzRIgAHPJQYbqYHKygWkDw6g==
typical@^4.0.0:
version "4.0.0"

View File

@@ -60,12 +60,12 @@
"git": {
"name": "electron",
"repositoryUrl": "https://github.com/electron/electron",
"commitHash": "0c2cb59b6283fe8d6bb4b14f8a832e2166aeaa0c"
"commitHash": "03c7a54dc534ce1867d4393b9b1a6989d4a7e005"
}
},
"isOnlyProductionDependency": true,
"license": "MIT",
"version": "9.2.0"
"version": "9.2.1"
},
{
"component": {

View File

@@ -54,7 +54,7 @@
"url": "vscode://schemas/keybindings"
},
{
"fileMatch": "vscode://defaultsettings/defaultSettings.json",
"fileMatch": "vscode://defaultsettings/*/*.json",
"url": "vscode://schemas/settings/default"
},
{

View File

@@ -15,7 +15,7 @@
"extensions": [ ".dockerfile", ".containerfile" ],
"filenames": [ "Dockerfile", "Containerfile" ],
"filenamePatterns": [ "Dockerfile.*", "Containerfile.*" ],
"aliases": [ "Dockerfile", "Containerfile" ],
"aliases": [ "Docker", "Dockerfile", "Containerfile" ],
"configuration": "./language-configuration.json"
}],
"grammars": [{

View File

@@ -754,13 +754,23 @@
"when": "scmProvider == git"
},
{
"command": "git.checkout",
"group": "1_header",
"command": "git.pull",
"group": "1_header@1",
"when": "scmProvider == git"
},
{
"command": "git.push",
"group": "1_header@2",
"when": "scmProvider == git"
},
{
"command": "git.clone",
"group": "1_header",
"group": "1_header@3",
"when": "scmProvider == git"
},
{
"command": "git.checkout",
"group": "1_header@4",
"when": "scmProvider == git"
},
{
@@ -1915,7 +1925,11 @@
"[git-commit]": {
"editor.rulers": [
72
]
],
"workbench.editor.restoreViewState": false
},
"[git-rebase]": {
"workbench.editor.restoreViewState": false
}
},
"viewsWelcome": [

View File

@@ -107,7 +107,7 @@
"config.smartCommitChanges.all": "Automatically stage all changes.",
"config.smartCommitChanges.tracked": "Automatically stage tracked changes only.",
"config.suggestSmartCommit": "Suggests to enable smart commit (commit all changes when there are no staged changes).",
"config.enableCommitSigning": "Enables commit signing with GPG.",
"config.enableCommitSigning": "Enables commit signing with GPG or X.509.",
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.",
"config.decorations.enabled": "Controls whether Git contributes colors and badges to the explorer and the open editors view.",
"config.enableStatusBarSync": "Controls whether the Git Sync command appears in the status bar.",

View File

@@ -460,7 +460,7 @@ export class CommandCenter {
@command('git.clone')
async clone(url?: string, parentPath?: string): Promise<void> {
if (!url) {
if (!url || typeof url !== 'string') {
url = await pickRemoteSource(this.model, {
providerLabel: provider => localize('clonefrom', "Clone from {0}", provider.name),
urlLabel: localize('repourl', "Clone from URL")

View File

@@ -232,7 +232,7 @@ export class GitTimelineProvider implements TimelineProvider {
private onRepositoryStatusChanged(_repo: Repository) {
// console.log(`GitTimelineProvider.onRepositoryStatusChanged`);
// This is crappy, but for now just save the last time a status was run and use that as the timestamp for staged items
// This is less than ideal, but for now just save the last time a status was run and use that as the timestamp for staged items
this.repoStatusDate = new Date();
this.fireChanged();

View File

@@ -11,15 +11,14 @@
"categories": [
"Other"
],
"activationEvents": [
"*",
"onAuthenticationRequest:github"
],
"extensionKind": [
"ui",
"workspace",
"web"
],
"activationEvents": [
"onAuthenticationRequest:github"
],
"contributes": {
"commands": [
{
@@ -34,7 +33,13 @@
"when": "false"
}
]
}
},
"authentication": [
{
"label": "GitHub",
"id": "github"
}
]
},
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js",

View File

@@ -22,7 +22,7 @@ export async function activate(context: vscode.ExtensionContext) {
return loginService.manuallyProvideToken();
}));
vscode.authentication.registerAuthenticationProvider({
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({
id: 'github',
label: 'GitHub',
supportsMultipleAccounts: false,
@@ -70,7 +70,7 @@ export async function activate(context: vscode.ExtensionContext) {
throw e;
}
}
});
}));
return;
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext } from 'vscode';
import { ExtensionContext, Uri } from 'vscode';
import { LanguageClientOptions } from 'vscode-languageclient';
import { startClient, LanguageClientConstructor } from '../jsonClient';
import { LanguageClient } from 'vscode-languageclient/browser';
@@ -17,9 +17,9 @@ declare function fetch(uri: string, options: any): any;
// this method is called when vs code is activated
export function activate(context: ExtensionContext) {
const serverMain = context.asAbsolutePath('server/dist/browser/jsonServerMain.js');
const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browser/jsonServerMain.js');
try {
const worker = new Worker(serverMain);
const worker = new Worker(serverMain.toString());
const newLanguageClient: LanguageClientConstructor = (id: string, name: string, clientOptions: LanguageClientOptions) => {
return new LanguageClient(id, name, clientOptions, worker);
};

View File

@@ -14,7 +14,7 @@
"dependencies": {
"jsonc-parser": "^2.2.1",
"request-light": "^0.3.0",
"vscode-json-languageservice": "^3.8.0",
"vscode-json-languageservice": "^3.8.3",
"vscode-languageserver": "7.0.0-next.3",
"vscode-uri": "^2.1.2"
},

View File

@@ -80,10 +80,10 @@ request-light@^0.3.0:
https-proxy-agent "^2.2.4"
vscode-nls "^4.1.1"
vscode-json-languageservice@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.8.0.tgz#c7e7283f993e3db39fa5501407b023ada6fd3ae3"
integrity sha512-sYz5JElJMIlPoqhrRfG3VKnDjnPinLdblIiEVsJgTz1kj2hWD2q5BSbo+evH/5/jKDXDLfA8kb0lHC4vd5g5zg==
vscode-json-languageservice@^3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.8.3.tgz#fae5e7bdda2b6ec4f64588c571df40b6bfcb09b5"
integrity sha512-8yPag/NQHCuTthahyaTtzK0DHT0FKM/xBU0mFBQ8nMo8C1i2P+FCyIVqICoNoHkRI2BTGlXKomPUpsqjSz0TnQ==
dependencies:
jsonc-parser "^2.2.1"
vscode-languageserver-textdocument "^1.0.1"

View File

@@ -12,7 +12,6 @@
],
"enableProposedApi": true,
"activationEvents": [
"*",
"onAuthenticationRequest:microsoft"
],
"extensionKind": [
@@ -20,6 +19,14 @@
"workspace",
"web"
],
"contributes": {
"authentication": [
{
"label": "Microsoft",
"id": "microsoft"
}
]
},
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js",
"browser": "./dist/browser/extension.js",

View File

@@ -5,6 +5,7 @@
import * as randomBytes from 'randombytes';
import * as querystring from 'querystring';
import { Buffer } from 'buffer';
import * as vscode from 'vscode';
import { createServer, startServer } from './authServer';
@@ -528,7 +529,7 @@ export class AzureActiveDirectoryService {
}
} catch (e) {
Logger.error('Refreshing token failed');
throw e;
throw new Error(REFRESH_NETWORK_FAILURE);
}
}

View File

@@ -42,7 +42,7 @@ export class ResourceTypeService implements IResourceTypeService {
vscode.extensions.all.forEach((extension) => {
const extensionResourceTypes = extension.packageJSON.contributes && extension.packageJSON.contributes.resourceDeploymentTypes as ResourceType[];
if (extensionResourceTypes) {
extensionResourceTypes.forEach((resourceType) => {
extensionResourceTypes.forEach((resourceType: ResourceType) => {
this.updatePathProperties(resourceType, extension.extensionPath);
resourceType.getProvider = (selectedOptions) => { return this.getProvider(resourceType, selectedOptions); };
this._resourceTypes.push(resourceType);

View File

@@ -233,6 +233,20 @@
"foreground": "#22aa44"
}
},
{
"name": "Markup: Strong",
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"name": "Markup: Emphasis",
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
@@ -242,11 +256,14 @@
}
},
{
"name": "Markup Setext Header",
"scope": "markup.heading.setext",
"name": "Markup Headings",
"scope": [
"markup.heading",
"markup.heading.setext"
],
"settings": {
"fontStyle": "",
"foreground": "#ddbb88"
"fontStyle": "bold",
"foreground": "#6688cc"
}
}
],

View File

@@ -136,6 +136,7 @@
{
"scope": "markup.heading",
"settings": {
"fontStyle": "bold",
"foreground": "#6796e6"
}
},

View File

@@ -260,7 +260,7 @@
"entity.name.section"
],
"settings": {
"fontStyle": "",
"fontStyle": "bold",
"foreground": "#8ab1b0"
}
},

View File

@@ -350,6 +350,20 @@
"foreground": "#fb9a4bff"
}
},
{
"name": "Markup: Strong",
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"name": "Markup: Emphasis",
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
@@ -359,17 +373,15 @@
}
},
{
"name": "Markup Headings",
"scope": "markup.heading",
"name": "Headings",
"scope": [
"markup.heading",
"markup.heading.setext",
"punctuation.definition.heading",
"entity.name.section"
],
"settings": {
"foreground": "#fec758ff"
}
},
{
"name": "Markup Setext Header",
"scope": "markup.heading.setext",
"settings": {
"fontStyle": "",
"fontStyle": "bold",
"foreground": "#fec758ff"
}
},

View File

@@ -305,7 +305,7 @@ exports.update = function () {
}
return download(fileAssociationFile).then(function (content) {
let regex2 = /\.icon-(?:set|partial)\(['"]([\w-\.]+)['"],\s*['"]([\w-]+)['"],\s*(@[\w-]+)\)/g;
let regex2 = /\.icon-(?:set|partial)\(['"]([\w-\.+]+)['"],\s*['"]([\w-]+)['"],\s*(@[\w-]+)\)/g;
while ((match = regex2.exec(content)) !== null) {
let pattern = match[1];
let def = '_' + match[2];

View File

@@ -6,7 +6,7 @@
"git": {
"name": "seti-ui",
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
"commitHash": "f3b2775662b0075aab56e5f0c03269f21f3f0f30"
"commitHash": "719e5d384e878b0e190abc80247a8726f083a393"
}
},
"version": "0.1.0"

File diff suppressed because it is too large Load Diff

View File

@@ -270,6 +270,20 @@
"foreground": "#D33682"
}
},
{
"name": "Markup: Strong",
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"name": "Markup: Emphasis",
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
@@ -282,6 +296,7 @@
"name": "Markup Headings",
"scope": "markup.heading",
"settings": {
"fontStyle": "bold",
"foreground": "#268BD2"
}
},

View File

@@ -273,6 +273,20 @@
"foreground": "#D33682"
}
},
{
"name": "Markup: Strong",
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"name": "Markup: Emphasis",
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
@@ -285,6 +299,7 @@
"name": "Markup Headings",
"scope": "markup.heading",
"settings": {
"fontStyle": "bold",
"foreground": "#268BD2"
}
},

View File

@@ -223,6 +223,20 @@
"foreground": "#FFC58F"
}
},
{
"name": "Markup: Strong",
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"name": "Markup: Emphasis",
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"name": "Markup Inline",
"scope": "markup.inline.raw",
@@ -231,6 +245,13 @@
"foreground": "#FF9DA4"
}
},
{
"name": "Markup Headings",
"scope": "markup.heading",
"settings": {
"fontStyle": "bold"
}
},
{
"scope": "token.info-token",
"settings": {

View File

@@ -40,6 +40,7 @@
"strict-vscode": "node --max_old_space_size=4095 node_modules/typescript/bin/tsc -p src/tsconfig.vscode.json",
"strict-vscode-watch": "node --max_old_space_size=4095 node_modules/typescript/bin/tsc -p src/tsconfig.vscode.json --watch",
"strict-initialization-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictPropertyInitialization",
"tsec-compile-check": "node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit",
"valid-layers-check": "node build/lib/layersChecker.js",
"strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes",
"update-distro": "node build/npm/update-distro.js",
@@ -73,7 +74,7 @@
"keytar": "^5.5.0",
"minimist": "^1.2.5",
"native-is-elevated": "0.4.1",
"native-keymap": "2.1.2",
"native-keymap": "2.2.0",
"native-watchdog": "1.3.0",
"ng2-charts": "^1.6.0",
"node-pty": "0.10.0-beta8",
@@ -128,7 +129,7 @@
"@typescript-eslint/eslint-plugin": "3.2.0",
"@typescript-eslint/parser": "^3.3.0",
"ansi-colors": "^3.2.3",
"asar": "^0.14.0",
"asar": "^3.0.3",
"chromium-pickle-js": "^0.2.0",
"concurrently": "^5.2.0",
"copy-webpack-plugin": "^4.5.2",
@@ -136,7 +137,7 @@
"css-loader": "^3.2.0",
"debounce": "^1.0.0",
"deemon": "^1.4.0",
"electron": "9.2.0",
"electron": "9.2.1",
"eslint": "6.8.0",
"eslint-plugin-jsdoc": "^19.1.0",
"event-stream": "3.3.4",
@@ -193,7 +194,8 @@
"temp-write": "^3.4.0",
"ts-loader": "^4.4.2",
"typemoq": "^0.3.2",
"typescript": "^4.0.1-rc",
"tsec": "googleinterns/tsec",
"typescript": "^4.1.0-dev.20200824",
"typescript-formatter": "7.1.0",
"underscore": "^1.8.2",
"vinyl": "^2.0.0",

View File

@@ -18,6 +18,7 @@ const fancyLog = require('fancy-log');
const ansiColors = require('ansi-colors');
const remote = require('gulp-remote-retry-src');
const vfs = require('vinyl-fs');
const uuid = require('uuid');
const extensions = require('../../build/lib/extensions');
@@ -27,21 +28,23 @@ const BUILTIN_MARKETPLACE_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'built
const WEB_DEV_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'builtInWebDevExtensions');
const WEB_MAIN = path.join(APP_ROOT, 'src', 'vs', 'code', 'browser', 'workbench', 'workbench-dev.html');
const WEB_PLAYGROUND_VERSION = '0.0.2';
const WEB_PLAYGROUND_VERSION = '0.0.8';
const args = minimist(process.argv, {
boolean: [
'no-launch',
'help',
'verbose',
'wrap-iframe'
'wrap-iframe',
'enable-sync'
],
string: [
'scheme',
'host',
'port',
'local_port',
'extension'
'extension',
'github-auth'
],
});
@@ -50,11 +53,13 @@ if (args.help) {
'yarn web [options]\n' +
' --no-launch Do not open VSCode web in the browser\n' +
' --wrap-iframe Wrap the Web Worker Extension Host in an iframe\n' +
' --enable-sync Enable sync by default\n' +
' --scheme Protocol (https or http)\n' +
' --host Remote host\n' +
' --port Remote/Local port\n' +
' --local_port Local port override\n' +
' --extension Path of an extension to include\n' +
' --github-auth Github authentication token\n' +
' --verbose Print out more information\n' +
' --help\n' +
'[Example]\n' +
@@ -356,14 +361,38 @@ async function handleRoot(req, res) {
const webConfigJSON = {
folderUri: folderUri,
staticExtensions,
enableSyncByDefault: args['enable-sync'],
};
if (args['wrap-iframe']) {
webConfigJSON._wrapWebWorkerExtHostInIframe = true;
}
const credentials = [];
if (args['github-auth']) {
const sessionId = uuid.v4();
credentials.push({
service: 'code-oss.login',
account: 'account',
password: JSON.stringify({
id: sessionId,
providerId: 'github',
accessToken: args['github-auth']
})
}, {
service: 'code-oss-github.login',
account: 'account',
password: JSON.stringify([{
id: sessionId,
scopes: ['user:email'],
accessToken: args['github-auth']
}])
});
}
const data = (await readFile(WEB_MAIN)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', () => escapeAttribute(JSON.stringify(webConfigJSON))) // use a replace function to avoid that regexp replace patterns ($&, $0, ...) are applied
.replace('{{WORKBENCH_BUILTIN_EXTENSIONS}}', () => escapeAttribute(JSON.stringify(dedupedBuiltInExtensions)))
.replace('{{WORKBENCH_CREDENTIALS}}', () => escapeAttribute(JSON.stringify(credentials)))
.replace('{{WEBVIEW_ENDPOINT}}', '')
.replace('{{REMOTE_USER_DATA_URI}}', '');

View File

@@ -16,6 +16,7 @@ exports.base = [{
}];
exports.workerExtensionHost = [entrypoint('vs/workbench/services/extensions/worker/extensionHostWorker')];
exports.workerNotebook = [entrypoint('vs/workbench/contrib/notebook/common/services/notebookSimpleWorker')];
exports.workbenchDesktop = require('./vs/workbench/buildfile.desktop').collectModules();
exports.workbenchWeb = require('./vs/workbench/buildfile.web').collectModules();

View File

@@ -92,7 +92,7 @@ export default class DiffEditorComponent extends ComponentBase implements ICompo
let editorinput1 = this._instantiationService.createInstance(ResourceEditorInput, uri1, 'source', undefined, undefined);
let editorinput2 = this._instantiationService.createInstance(ResourceEditorInput, uri2, 'target', undefined, undefined);
this._editorInput = new DiffEditorInput('DiffEditor', undefined, editorinput1, editorinput2, true);
this._editor.setInput(this._editorInput, undefined, cancellationTokenSource.token);
this._editor.setInput(this._editorInput, undefined, undefined, cancellationTokenSource.token);
this._editorInput.resolve().then(model => {

View File

@@ -70,7 +70,7 @@ export default class EditorComponent extends ComponentBase implements IComponent
this._editor.setVisible(true);
let uri = this.createUri();
this._editorInput = this.editorService.createEditorInput({ forceUntitled: true, resource: uri, mode: 'plaintext' }) as UntitledTextEditorInput;
await this._editor.setInput(this._editorInput, undefined);
await this._editor.setInput(this._editorInput, undefined, undefined);
const model = await this._editorInput.resolve();
this._editorModel = model.textEditorModel;
this.fireEvent({

View File

@@ -6,15 +6,15 @@ import 'vs/css!./media/modelViewEditor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import * as DOM from 'vs/base/browser/dom';
import { ModelViewInput } from 'sql/workbench/browser/modelComponents/modelViewInput';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
export class ModelViewEditor extends BaseEditor {
export class ModelViewEditor extends EditorPane {
public static ID: string = 'workbench.editor.modelViewEditor';
@@ -62,7 +62,7 @@ export class ModelViewEditor extends BaseEditor {
}
}
async setInput(input: ModelViewInput, options?: EditorOptions): Promise<void> {
async setInput(input: ModelViewInput, options?: EditorOptions, context?: IEditorOpenContext): Promise<void> {
if (this.input && this.input.matches(input)) {
return Promise.resolve(undefined);
}
@@ -73,7 +73,7 @@ export class ModelViewEditor extends BaseEditor {
input.container.style.visibility = 'visible';
this._content.setAttribute('aria-flowto', input.container.id);
await super.setInput(input, options, CancellationToken.None);
await super.setInput(input, options, context, CancellationToken.None);
this.doUpdateContainer();
}

View File

@@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
@@ -85,8 +85,8 @@ export class QueryTextEditor extends BaseTextEditor {
return options;
}
setInput(input: UntitledTextEditorInput, options: EditorOptions): Promise<void> {
return super.setInput(input, options, CancellationToken.None)
setInput(input: UntitledTextEditorInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
return super.setInput(input, options, context, CancellationToken.None)
.then(() => this.input.resolve()
.then(editorModel => editorModel.load())
.then(editorModel => this.getControl().setModel((<ResourceEditorModel>editorModel).textEditorModel)));

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { EditorOptions } from 'vs/workbench/common/editor';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -25,7 +25,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IQueryManagementService } from 'sql/workbench/services/query/common/queryManagement';
export class DashboardEditor extends BaseEditor {
export class DashboardEditor extends EditorPane {
public static ID: string = 'workbench.editor.connectiondashboard';
private _dashboardContainer: HTMLElement;
@@ -77,14 +77,14 @@ export class DashboardEditor extends BaseEditor {
this._dashboardService.layout(dimension);
}
public async setInput(input: DashboardInput, options: EditorOptions): Promise<void> {
public async setInput(input: DashboardInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
if (this.input && this.input.matches(input)) {
return Promise.resolve(undefined);
}
const parentElement = this.getContainer();
super.setInput(input, options, CancellationToken.None);
super.setInput(input, options, context, CancellationToken.None);
DOM.clearNode(parentElement);

View File

@@ -7,8 +7,8 @@ import * as strings from 'vs/base/common/strings';
import * as DOM from 'vs/base/browser/dom';
import * as nls from 'vs/nls';
import { EditorOptions, EditorInput, IEditorControl, IEditorPane } from 'vs/workbench/common/editor';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, EditorInput, IEditorControl, IEditorPane, IEditorOpenContext } from 'vs/workbench/common/editor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -41,7 +41,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
/**
* Editor that hosts an action bar and a resultSetInput for an edit data session
*/
export class EditDataEditor extends BaseEditor {
export class EditDataEditor extends EditorPane {
public static ID: string = 'workbench.editor.editDataEditor';
@@ -213,7 +213,7 @@ export class EditDataEditor extends BaseEditor {
/**
* Sets the input data for this editor.
*/
public setInput(newInput: EditDataInput, options?: EditorOptions): Promise<void> {
public setInput(newInput: EditDataInput, options?: EditorOptions, context?: IEditorOpenContext): Promise<void> {
let oldInput = <EditDataInput>this.input;
if (!newInput.setup) {
this._initialized = false;
@@ -224,7 +224,7 @@ export class EditDataEditor extends BaseEditor {
newInput.setupComplete();
}
return super.setInput(newInput, options, CancellationToken.None)
return super.setInput(newInput, options, context, CancellationToken.None)
.then(() => this._updateInput(oldInput, newInput, options));
}
@@ -251,7 +251,7 @@ export class EditDataEditor extends BaseEditor {
}
// PRIVATE METHODS ////////////////////////////////////////////////////////////
private _createEditor(editorInput: EditorInput, container: HTMLElement): Promise<BaseEditor> {
private _createEditor(editorInput: EditorInput, container: HTMLElement): Promise<EditorPane> {
const descriptor = this._editorDescriptorService.getEditor(editorInput);
if (!descriptor) {
return Promise.reject(new Error(strings.format('Can not find a registered editor for the input {0}', editorInput)));
@@ -493,7 +493,7 @@ export class EditDataEditor extends BaseEditor {
*/
private _onResultsEditorCreated(resultsEditor: EditDataResultsEditor, resultsInput: EditDataResultsInput, options: EditorOptions): Promise<void> {
this._resultsEditor = resultsEditor;
return this._resultsEditor.setInput(resultsInput, options);
return this._resultsEditor.setInput(resultsInput, options, undefined);
}
/**
@@ -501,7 +501,7 @@ export class EditDataEditor extends BaseEditor {
*/
private _onSqlEditorCreated(sqlEditor: TextResourceEditor, sqlInput: UntitledTextEditorInput, options: EditorOptions): Thenable<void> {
this._sqlEditor = sqlEditor;
return this._sqlEditor.setInput(sqlInput, options, CancellationToken.None);
return this._sqlEditor.setInput(sqlInput, options, undefined, CancellationToken.None);
}
private _resizeGridContents(): void {

View File

@@ -5,13 +5,13 @@
import * as DOM from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { getZoomLevel } from 'vs/base/browser/browser';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import * as types from 'vs/base/common/types';
import { IQueryModelService } from 'sql/workbench/services/query/common/queryModel';
@@ -21,7 +21,7 @@ import { EditDataResultsInput } from 'sql/workbench/browser/editData/editDataRes
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
export class EditDataResultsEditor extends BaseEditor {
export class EditDataResultsEditor extends EditorPane {
public static ID: string = 'workbench.editor.editDataResultsEditor';
protected _input: EditDataResultsInput;
@@ -63,8 +63,8 @@ export class EditDataResultsEditor extends BaseEditor {
public layout(dimension: DOM.Dimension): void {
}
public setInput(input: EditDataResultsInput, options: EditorOptions): Promise<void> {
super.setInput(input, options, CancellationToken.None);
public setInput(input: EditDataResultsInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
super.setInput(input, options, context, CancellationToken.None);
this._applySettings();
if (!input.hasBootstrapped) {
this.createGridPanel();

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { IProductService } from 'vs/platform/product/common/productService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -19,6 +19,7 @@ import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { InstallRecommendedExtensionsByScenarioAction, ShowRecommendedExtensionsByScenarioAction } from 'sql/workbench/contrib/extensions/browser/extensionsActions';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
const choiceNever = localize('neverShowAgain', "Don't Show Again");
@@ -28,18 +29,20 @@ export class ScenarioRecommendations extends ExtensionRecommendations {
get recommendations(): ReadonlyArray<ExtensionRecommendation> { return this._recommendations; }
constructor(
isExtensionAllowedToBeRecommended: (extensionId: string) => boolean,
promptedExtensionRecommendations: PromptedExtensionRecommendations,
@IProductService private readonly productService: IProductService,
@IInstantiationService instantiationService: IInstantiationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@INotificationService notificationService: INotificationService,
@INotificationService private readonly notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IStorageService private readonly storageService: IStorageService,
@IExtensionManagementService protected readonly extensionManagementService: IExtensionManagementService,
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService,
@IExtensionsWorkbenchService protected readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super(isExtensionAllowedToBeRecommended, instantiationService, configurationService, notificationService, telemetryService, storageService, storageKeysSyncRegistryService);
super(promptedExtensionRecommendations);
// this._recommendations = productService.recommendedExtensionsByScenario.map(r => ({ extensionId: r, reason: { reasonId: ExtensionRecommendationReason.Application, reasonText: localize('defaultRecommendations', "This extension is recommended by Azure Data Studio.") }, source: 'application' }));
}
@@ -123,12 +126,11 @@ export class ScenarioRecommendations extends ExtensionRecommendations {
});
}
getRecommendedExtensionsByScenario(scenarioType: string): Promise<IExtensionRecommendation[]> {
async getRecommendedExtensionsByScenario(scenarioType: string): Promise<IExtensionRecommendation[]> {
if (!scenarioType) {
return Promise.reject(new Error(localize('scenarioTypeUndefined', 'The scenario type for extension recommendations must be provided.')));
}
return Promise.resolve((this.productService.recommendedExtensionsByScenario[scenarioType] || [])
.filter(extensionId => this.isExtensionAllowedToBeRecommended(extensionId))
.map(extensionId => (<IExtensionRecommendation>{ extensionId, sources: ['application'] })));
return this.promptedExtensionRecommendations.filterIgnoredOrNotAllowed(this.productService.recommendedExtensionsByScenario[scenarioType] || [])
.map(extensionId => (<IExtensionRecommendation>{ extensionId, sources: ['application'] }));
}
}

View File

@@ -3,16 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { IProductService } from 'vs/platform/product/common/productService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { localize } from 'vs/nls';
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
export class StaticRecommendations extends ExtensionRecommendations {
@@ -20,16 +14,10 @@ export class StaticRecommendations extends ExtensionRecommendations {
get recommendations(): ReadonlyArray<ExtensionRecommendation> { return this._recommendations; }
constructor(
isExtensionAllowedToBeRecommended: (extensionId: string) => boolean,
@IProductService productService: IProductService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@INotificationService notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
promptedExtensionRecommendations: PromptedExtensionRecommendations,
@IProductService productService: IProductService
) {
super(isExtensionAllowedToBeRecommended, instantiationService, configurationService, notificationService, telemetryService, storageService, storageKeysSyncRegistryService);
super(promptedExtensionRecommendations);
this._recommendations = productService.recommendedExtensions.map(r => ({ extensionId: r, reason: { reasonId: ExtensionRecommendationReason.Application, reasonText: localize('defaultRecommendations', "This extension is recommended by Azure Data Studio.") }, source: 'application' }));
}

View File

@@ -203,7 +203,7 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
cellModelSource = Array.isArray(this.cellModel.source) ? this.cellModel.source.join('') : this.cellModel.source;
const model = this._instantiationService.createInstance(UntitledTextEditorModel, uri, false, cellModelSource, this.cellModel.language, undefined);
this._editorInput = this._instantiationService.createInstance(UntitledTextEditorInput, model);
await this._editor.setInput(this._editorInput, undefined);
await this._editor.setInput(this._editorInput, undefined, undefined);
this.setFocusAndScroll();
let untitledEditorModel = await this._editorInput.resolve() as UntitledTextEditorModel;

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import * as DOM from 'vs/base/browser/dom';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -35,7 +35,7 @@ import { TimeoutTimer } from 'vs/base/common/async';
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
import { onUnexpectedError } from 'vs/base/common/errors';
export class NotebookEditor extends BaseEditor implements IFindNotebookController {
export class NotebookEditor extends EditorPane implements IFindNotebookController {
public static ID: string = 'workbench.editor.notebookEditor';
private _notebookContainer: HTMLElement;
@@ -187,14 +187,14 @@ export class NotebookEditor extends BaseEditor implements IFindNotebookControlle
}
}
public async setInput(input: NotebookInput, options: EditorOptions): Promise<void> {
public async setInput(input: NotebookInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
if (this.input && this.input.matches(input)) {
return Promise.resolve(undefined);
}
const parentElement = this.getContainer();
await super.setInput(input, options, CancellationToken.None);
await super.setInput(input, options, context, CancellationToken.None);
DOM.clearNode(parentElement);
await this.setFindInput(parentElement);
if (!input.hasBootstrapped) {

View File

@@ -126,7 +126,7 @@ suite.skip('Test class NotebookEditor:', () => {
const testNotebookEditor = new NotebookEditorStub({ cellGuid: cellTextEditorGuid, editor: queryTextEditor, model: notebookModel, notebookParams: <INotebookParams>{ notebookUri: untitledNotebookInput.notebookUri } });
notebookService.addNotebookEditor(testNotebookEditor);
notebookEditor.clearInput();
await notebookEditor.setInput(untitledNotebookInput, EditorOptions.create({ pinned: true }));
await notebookEditor.setInput(untitledNotebookInput, EditorOptions.create({ pinned: true }), undefined);
untitledNotebookInput.notebookFindModel.notebookModel = undefined; // clear preexisting notebookModel
const result = await notebookEditor.getNotebookModel();
assert.strictEqual(result, notebookModel, `getNotebookModel() should return the model set in the INotebookEditor object`);
@@ -214,7 +214,7 @@ suite.skip('Test class NotebookEditor:', () => {
untitledNotebookInput /* set to a known input */,
untitledNotebookInput /* tries to set the same input that was previously set */
]) {
await notebookEditor.setInput(input, editorOptions);
await notebookEditor.setInput(input, editorOptions, undefined);
assert.strictEqual(notebookEditor.input, input, `notebookEditor.input should be the one that we set`);
}
});
@@ -225,7 +225,7 @@ suite.skip('Test class NotebookEditor:', () => {
for (const isRevealed of [true, false]) {
notebookEditor['_findState']['_isRevealed'] = isRevealed;
notebookEditor.clearInput();
await notebookEditor.setInput(untitledNotebookInput, editorOptions);
await notebookEditor.setInput(untitledNotebookInput, editorOptions, undefined);
assert.strictEqual(notebookEditor.input, untitledNotebookInput, `notebookEditor.input should be the one that we set`);
}
});
@@ -744,7 +744,7 @@ async function setupNotebookEditor(notebookEditor: NotebookEditor, untitledNoteb
async function setInputDocument(notebookEditor: NotebookEditor, untitledNotebookInput: UntitledNotebookInput): Promise<void> {
const editorOptions = EditorOptions.create({ pinned: true });
await notebookEditor.setInput(untitledNotebookInput, editorOptions);
await notebookEditor.setInput(untitledNotebookInput, editorOptions, undefined);
assert.strictEqual(notebookEditor.options, editorOptions, 'NotebookEditor options must be the ones that we set');
}

View File

@@ -38,7 +38,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IView, SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import * as DOM from 'vs/base/browser/dom';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { EditorOptions } from 'vs/workbench/common/editor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkbenchThemeService, VS_DARK_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService';
@@ -117,7 +117,7 @@ export interface IDetailData {
value: string;
}
export class ProfilerEditor extends BaseEditor {
export class ProfilerEditor extends EditorPane {
public static readonly ID: string = 'workbench.editor.profiler';
private _untitledTextEditorModel: UntitledTextEditorModel;
@@ -440,7 +440,7 @@ export class ProfilerEditor extends BaseEditor {
this._editor.setVisible(true);
this._untitledTextEditorModel = this._instantiationService.createInstance(UntitledTextEditorModel, URI.from({ scheme: Schemas.untitled }), false, undefined, 'sql', undefined);
this._editorInput = this._instantiationService.createInstance(UntitledTextEditorInput, this._untitledTextEditorModel);
this._editor.setInput(this._editorInput, undefined);
this._editor.setInput(this._editorInput, undefined, undefined);
this._editorInput.resolve().then(model => this._editorModel = model.textEditorModel);
return editorContainer;
}
@@ -460,7 +460,7 @@ export class ProfilerEditor extends BaseEditor {
return Promise.resolve(null);
}
return super.setInput(input, options, CancellationToken.None).then(() => {
return super.setInput(input, options, undefined, CancellationToken.None).then(() => {
this._profilerTableEditor.setInput(input);
if (input.viewTemplate) {

View File

@@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -75,8 +75,8 @@ export class ProfilerResourceEditor extends BaseTextEditor {
return options;
}
setInput(input: UntitledTextEditorInput, options: EditorOptions): Promise<void> {
return super.setInput(input, options, CancellationToken.None)
setInput(input: UntitledTextEditorInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
return super.setInput(input, options, context, CancellationToken.None)
.then(() => this.input.resolve()
.then(editorModel => editorModel.load())
.then(editorModel => this.getControl().setModel((<ResourceEditorModel>editorModel).textEditorModel)));

View File

@@ -20,7 +20,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IEditorAction } from 'vs/editor/common/editorCommon';
import { IOverlayWidget } from 'vs/editor/browser/editorBrowser';
import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Event, Emitter } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -39,7 +39,7 @@ export interface ProfilerTableViewState {
scrollLeft: number;
}
export class ProfilerTableEditor extends BaseEditor implements IProfilerController, ITableController {
export class ProfilerTableEditor extends EditorPane implements IProfilerController, ITableController {
public static ID: string = 'workbench.editor.profiler.table';
protected _input: ProfilerInput;

View File

@@ -7,8 +7,8 @@ import 'vs/css!./media/queryEditor';
import * as DOM from 'vs/base/browser/dom';
import * as path from 'vs/base/common/path';
import { EditorOptions, IEditorControl, IEditorMemento } from 'vs/workbench/common/editor';
import { BaseEditor, EditorMemento } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, IEditorControl, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor';
import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
import { Orientation } from 'vs/base/browser/ui/sash/sash';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -50,7 +50,7 @@ interface IQueryEditorViewState {
* Editor that hosts 2 sub-editors: A TextResourceEditor for SQL file editing, and a QueryResultsEditor
* for viewing and editing query results. This editor is based off SideBySideEditor.
*/
export class QueryEditor extends BaseEditor {
export class QueryEditor extends EditorPane {
public static ID: string = 'workbench.editor.queryEditor';
@@ -320,7 +320,7 @@ export class QueryEditor extends BaseEditor {
this.taskbar.setContent(content);
}
public async setInput(newInput: QueryEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
public async setInput(newInput: QueryEditorInput, options: EditorOptions, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
const oldInput = this.input;
if (newInput.matches(oldInput)) {
@@ -350,9 +350,9 @@ export class QueryEditor extends BaseEditor {
}
await Promise.all([
super.setInput(newInput, options, token),
this.currentTextEditor.setInput(newInput.text, options, token),
this.resultsEditor.setInput(newInput.results, options)
super.setInput(newInput, options, context, token),
this.currentTextEditor.setInput(newInput.text, options, context, token),
this.resultsEditor.setInput(newInput.results, options, context)
]);
this.inputDisposables.clear();

View File

@@ -3,10 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { getZoomLevel } from 'vs/base/browser/browser';
@@ -71,7 +71,7 @@ export function getBareResultsGridInfoStyles(info: BareResultsGridInfo): string
/**
* Editor associated with viewing and editing the data of a query results grid.
*/
export class QueryResultsEditor extends BaseEditor {
export class QueryResultsEditor extends EditorPane {
public static ID: string = 'workbench.editor.queryResultsEditor';
protected _rawOptions: BareResultsGridInfo;
@@ -131,8 +131,8 @@ export class QueryResultsEditor extends BaseEditor {
this.resultsView.layout(dimension);
}
setInput(input: QueryResultsInput, options: EditorOptions): Promise<void> {
super.setInput(input, options, CancellationToken.None);
setInput(input: QueryResultsInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
super.setInput(input, options, context, CancellationToken.None);
this.resultsView.input = input;
return Promise.resolve<void>(null);
}

View File

@@ -16,7 +16,7 @@ import { EditorDescriptorService } from 'sql/workbench/services/queryEditor/brow
import * as TypeMoq from 'typemoq';
import * as assert from 'assert';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
@@ -76,7 +76,7 @@ suite('SQL QueryEditor Tests', () => {
getId: function (): string { return 'id'; },
getName: function (): string { return 'name'; },
describes: function (obj: any): boolean { return true; },
instantiate(instantiationService: IInstantiationService): BaseEditor { return undefined; }
instantiate(instantiationService: IInstantiationService): EditorPane { return undefined; }
};
editorDescriptorService = TypeMoq.Mock.ofType(EditorDescriptorService, TypeMoq.MockBehavior.Loose);
editorDescriptorService.setup(x => x.getEditor(TypeMoq.It.isAny())).returns(() => descriptor);

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { EditorOptions } from 'vs/workbench/common/editor';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { QueryPlanInput } from 'sql/workbench/contrib/queryPlan/common/queryPlanInput';
@@ -13,7 +13,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { QueryPlanView } from 'sql/workbench/contrib/queryPlan/browser/queryPlan';
export class QueryPlanEditor extends BaseEditor {
export class QueryPlanEditor extends EditorPane {
public static ID: string = 'workbench.editor.queryplan';
@@ -60,13 +60,13 @@ export class QueryPlanEditor extends BaseEditor {
this.view.layout(dimension);
}
public async setInput(input: QueryPlanInput, options: EditorOptions): Promise<void> {
public async setInput(input: QueryPlanInput, options: EditorOptions, context: IEditorOpenContext): Promise<void> {
if (this.input instanceof QueryPlanInput && this.input.matches(input)) {
return Promise.resolve(undefined);
}
await input.resolve();
await super.setInput(input, options, CancellationToken.None);
await super.setInput(input, options, context, CancellationToken.None);
this.view.showPlan(input.planXml!);
}

View File

@@ -8,16 +8,16 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import * as DOM from 'vs/base/browser/dom';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions } from 'vs/workbench/common/editor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IResourceViewerStateChangedEvent } from 'sql/workbench/common/editor/resourceViewer/resourceViewerState';
import { ResourceViewerInput } from 'sql/workbench/browser/editor/resourceViewer/resourceViewerInput';
import { ResourceViewerTable } from 'sql/workbench/contrib/resourceViewer/browser/resourceViewerTable';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
export class ResourceViewerEditor extends BaseEditor {
export class ResourceViewerEditor extends EditorPane {
public static readonly ID: string = 'workbench.editor.resource-viewer';
private _container!: HTMLElement;
@@ -72,8 +72,8 @@ export class ResourceViewerEditor extends BaseEditor {
return this._input as ResourceViewerInput;
}
public async setInput(input: ResourceViewerInput, options?: EditorOptions): Promise<void> {
await super.setInput(input, options, CancellationToken.None);
async setInput(input: ResourceViewerInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
await super.setInput(input, options, context, token);
this._inputDisposables.clear();

View File

@@ -25,6 +25,7 @@
},
"lib": [
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"DOM",

View File

@@ -15,7 +15,6 @@
"include": [
"typings/require.d.ts",
"typings/thenable.d.ts",
"typings/lib.array-ext.d.ts",
"vs/css.d.ts",
"vs/monaco.d.ts",
"vs/nls.d.ts",

View File

@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { renderCodiconsRegex } from 'vs/base/common/codicons';
export function renderCodiconsAsElement(text: string): Array<HTMLSpanElement | string> {
const elements = new Array<HTMLSpanElement | string>();
let match: RegExpMatchArray | null;
let textStart = 0, textStop = 0;
while ((match = renderCodiconsRegex.exec(text)) !== null) {
textStop = match.index || 0;
elements.push(text.substring(textStart, textStop));
textStart = (match.index || 0) + match[0].length;
const [, escaped, codicon, name, animation] = match;
elements.push(escaped ? `$(${codicon})` : dom.$(`span.codicon.codicon-${name}${animation ? `.codicon-animation-${animation}` : ''}`));
}
if (textStart < text.length) {
elements.push(text.substring(textStart));
}
return elements;
}

View File

@@ -997,6 +997,11 @@ export function trackFocus(element: HTMLElement | Window): IFocusTracker {
return new FocusTracker(element);
}
export function after<T extends Node>(sibling: HTMLElement, child: T): T {
sibling.after(child);
return child;
}
export function append<T extends Node>(parent: HTMLElement, ...children: T[]): T {
children.forEach(child => parent.appendChild(child));
return children[children.length - 1];
@@ -1009,6 +1014,18 @@ export function prepend<T extends Node>(parent: HTMLElement, child: T): T {
const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/;
export function reset<T extends Node>(parent: HTMLElement, ...children: Array<Node | string>) {
parent.innerText = '';
coalesce(children)
.forEach(child => {
if (child instanceof Node) {
parent.appendChild(child);
} else {
parent.appendChild(document.createTextNode(child as string));
}
});
}
export enum Namespace {
HTML = 'http://www.w3.org/1999/xhtml',
SVG = 'http://www.w3.org/2000/svg'

View File

@@ -205,6 +205,40 @@ const altKeyMod = KeyMod.Alt;
const shiftKeyMod = KeyMod.Shift;
const metaKeyMod = (platform.isMacintosh ? KeyMod.CtrlCmd : KeyMod.WinCtrl);
export function printKeyboardEvent(e: KeyboardEvent): string {
let modifiers: string[] = [];
if (e.ctrlKey) {
modifiers.push(`ctrl`);
}
if (e.shiftKey) {
modifiers.push(`shift`);
}
if (e.altKey) {
modifiers.push(`alt`);
}
if (e.metaKey) {
modifiers.push(`meta`);
}
return `modifiers: [${modifiers.join(',')}], code: ${e.code}, keyCode: ${e.keyCode}, key: ${e.key}`;
}
export function printStandardKeyboardEvent(e: StandardKeyboardEvent): string {
let modifiers: string[] = [];
if (e.ctrlKey) {
modifiers.push(`ctrl`);
}
if (e.shiftKey) {
modifiers.push(`shift`);
}
if (e.altKey) {
modifiers.push(`alt`);
}
if (e.metaKey) {
modifiers.push(`meta`);
}
return `modifiers: [${modifiers.join(',')}], code: ${e.code}, keyCode: ${e.keyCode} ('${KeyCodeUtils.toString(e.keyCode)}')`;
}
export class StandardKeyboardEvent implements IKeyboardEvent {
readonly _standardKeyboardEventBrand = true;

View File

@@ -12,8 +12,7 @@ import { mixin } from 'vs/base/common/objects';
import { Event as BaseEvent, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Gesture, EventType } from 'vs/base/browser/touch';
import { renderCodicons } from 'vs/base/common/codicons';
import { escape } from 'vs/base/common/strings';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
export interface IButtonOptions extends IButtonStyles {
readonly title?: boolean | string;
@@ -181,7 +180,7 @@ export class Button extends Disposable {
DOM.addClass(this._element, 'monaco-text-button');
}
if (this.options.supportCodicons) {
this._element.innerHTML = renderCodicons(escape(value));
DOM.reset(this._element, ...renderCodiconsAsElement(value));
} else {
this._element.textContent = value;
}

View File

@@ -3,8 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { escape } from 'vs/base/common/strings';
import { renderCodicons } from 'vs/base/common/codicons';
import { reset } from 'vs/base/browser/dom';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
export class CodiconLabel {
@@ -13,7 +13,7 @@ export class CodiconLabel {
) { }
set text(text: string) {
this._container.innerHTML = renderCodicons(escape(text ?? ''));
reset(this._container, ...renderCodiconsAsElement(text ?? ''));
}
set title(title: string) {

View File

@@ -121,7 +121,7 @@ export class ExternalElementsDragAndDropData<T> implements IDragAndDropData {
}
}
export class DesktopDragAndDropData implements IDragAndDropData {
export class NativeDragAndDropData implements IDragAndDropData {
readonly types: any[];
readonly files: any[];
@@ -976,7 +976,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
return false;
}
this.currentDragData = new DesktopDragAndDropData();
this.currentDragData = new NativeDragAndDropData();
}
}

View File

@@ -24,6 +24,7 @@ export interface IPaneOptions {
expanded?: boolean;
orientation?: Orientation;
title: string;
titleDescription?: string;
}
export interface IPaneStyles {

View File

@@ -590,17 +590,6 @@ export function asArray<T>(x: T | T[]): T[] {
return Array.isArray(x) ? x : [x];
}
/**
* @deprecated Use `Array.from` or `[...iter]`
*/
export function toArray<T>(iterable: IterableIterator<T>): T[] {
const result: T[] = [];
for (let element of iterable) {
result.push(element);
}
return result;
}
export function getRandomElement<T>(arr: T[]): T | undefined {
return arr[Math.floor(Math.random() * arr.length)];
}

View File

@@ -170,6 +170,25 @@ export class Sequencer {
}
}
export class SequencerByKey<TKey> {
private promiseMap = new Map<TKey, Promise<any>>();
queue<T>(key: TKey, promiseTask: ITask<Promise<T>>): Promise<T> {
const runningPromise = this.promiseMap.get(key) ?? Promise.resolve();
const newPromise = runningPromise
.catch(() => { })
.then(promiseTask)
.finally(() => {
if (this.promiseMap.get(key) === newPromise) {
this.promiseMap.delete(key);
}
});
this.promiseMap.set(key, newPromise);
return newPromise;
}
}
/**
* A helper to delay execution of a task that is being requested often.
*

View File

@@ -499,7 +499,11 @@ export function markdownUnescapeCodicons(text: string): string {
return text.replace(markdownUnescapeCodiconsRegex, (match, escaped, codicon) => escaped ? match : `$(${codicon})`);
}
const renderCodiconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi;
export const renderCodiconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi;
/**
* @deprecated Use `renderCodiconsAsElement` instead
*/
export function renderCodicons(text: string): string {
return text.replace(renderCodiconsRegex, (_, escaped, codicon, name, animation) => {
// If the class for codicons is changed, it should also be updated in src\vs\base\browser\markdownRenderer.ts

View File

@@ -142,7 +142,7 @@ export function isUNC(path: string): boolean {
// Reference: https://en.wikipedia.org/wiki/Filename
const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g;
const UNIX_INVALID_FILE_CHARS = /[\\/]/g;
const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i;
const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])(\.(.*?))?$/i;
export function isValidBasename(name: string | null | undefined, isWindowsOS: boolean = isWindows): boolean {
const invalidFileChars = isWindowsOS ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS;

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { compareAnything } from 'vs/base/common/comparers';
import { matchesPrefix, IMatch, isUpper, fuzzyScore, createMatches as createFuzzyMatches, matchesStrictPrefix } from 'vs/base/common/filters';
import { matchesPrefix, IMatch, isUpper, fuzzyScore, createMatches as createFuzzyMatches } from 'vs/base/common/filters';
import { sep } from 'vs/base/common/path';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { stripWildcards, equalsIgnoreCase } from 'vs/base/common/strings';
@@ -369,9 +369,8 @@ export interface IItemAccessor<T> {
}
const PATH_IDENTITY_SCORE = 1 << 18;
const LABEL_PREFIX_SCORE_MATCHCASE = 1 << 17;
const LABEL_PREFIX_SCORE_IGNORECASE = 1 << 16;
const LABEL_SCORE_THRESHOLD = 1 << 15;
const LABEL_PREFIX_SCORE_THRESHOLD = 1 << 17;
const LABEL_SCORE_THRESHOLD = 1 << 16;
export function scoreItemFuzzy<T>(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor<T>, cache: FuzzyScorerCache): IItemScore {
if (!item || !query.normalized) {
@@ -460,20 +459,33 @@ function doScoreItemFuzzyMultiple(label: string, description: string | undefined
function doScoreItemFuzzySingle(label: string, description: string | undefined, path: string | undefined, query: IPreparedQueryPiece, preferLabelMatches: boolean, fuzzy: boolean): IItemScore {
// Prefer label matches if told so
if (preferLabelMatches) {
// Treat prefix matches on the label highest
const prefixLabelMatchIgnoreCase = matchesPrefix(query.normalized, label);
if (prefixLabelMatchIgnoreCase) {
const prefixLabelMatchStrictCase = matchesStrictPrefix(query.normalized, label);
return { score: prefixLabelMatchStrictCase ? LABEL_PREFIX_SCORE_MATCHCASE : LABEL_PREFIX_SCORE_IGNORECASE, labelMatch: prefixLabelMatchStrictCase || prefixLabelMatchIgnoreCase };
}
// Second, score fuzzy
// Prefer label matches if told so or we have no description
if (preferLabelMatches || !description) {
const [labelScore, labelPositions] = scoreFuzzy(label, query.normalized, query.normalizedLowercase, fuzzy);
if (labelScore) {
return { score: labelScore + LABEL_SCORE_THRESHOLD, labelMatch: createMatches(labelPositions) };
// If we have a prefix match on the label, we give a much
// higher baseScore to elevate these matches over others
// This ensures that typing a file name wins over results
// that are present somewhere in the label, but not the
// beginning.
const labelPrefixMatch = matchesPrefix(query.normalized, label);
let baseScore: number;
if (labelPrefixMatch) {
baseScore = LABEL_PREFIX_SCORE_THRESHOLD;
// We give another boost to labels that are short, e.g. given
// files "window.ts" and "windowActions.ts" and a query of
// "window", we want "window.ts" to receive a higher score.
// As such we compute the percentage the query has within the
// label and add that to the baseScore.
const prefixLengthBoost = Math.round((query.normalized.length / label.length) * 100);
baseScore += prefixLengthBoost;
} else {
baseScore = LABEL_SCORE_THRESHOLD;
}
return { score: baseScore + labelScore, labelMatch: labelPrefixMatch || createMatches(labelPositions) };
}
}
@@ -600,46 +612,19 @@ export function compareItemsByFuzzyScore<T>(itemA: T, itemB: T, query: IPrepared
}
}
// 2.) prefer label prefix matches (match case)
if (scoreA === LABEL_PREFIX_SCORE_MATCHCASE || scoreB === LABEL_PREFIX_SCORE_MATCHCASE) {
if (scoreA !== scoreB) {
return scoreA === LABEL_PREFIX_SCORE_MATCHCASE ? -1 : 1;
}
const labelA = accessor.getItemLabel(itemA) || '';
const labelB = accessor.getItemLabel(itemB) || '';
// prefer shorter names when both match on label prefix
if (labelA.length !== labelB.length) {
return labelA.length - labelB.length;
}
}
// 3.) prefer label prefix matches (ignore case)
if (scoreA === LABEL_PREFIX_SCORE_IGNORECASE || scoreB === LABEL_PREFIX_SCORE_IGNORECASE) {
if (scoreA !== scoreB) {
return scoreA === LABEL_PREFIX_SCORE_IGNORECASE ? -1 : 1;
}
const labelA = accessor.getItemLabel(itemA) || '';
const labelB = accessor.getItemLabel(itemB) || '';
// prefer shorter names when both match on label prefix
if (labelA.length !== labelB.length) {
return labelA.length - labelB.length;
}
}
// 4.) matches on label are considered higher compared to label+description matches
// 2.) matches on label are considered higher compared to label+description matches
if (scoreA > LABEL_SCORE_THRESHOLD || scoreB > LABEL_SCORE_THRESHOLD) {
if (scoreA !== scoreB) {
return scoreA > scoreB ? -1 : 1;
}
// prefer more compact matches over longer in label
const comparedByMatchLength = compareByMatchLength(itemScoreA.labelMatch, itemScoreB.labelMatch);
if (comparedByMatchLength !== 0) {
return comparedByMatchLength;
// prefer more compact matches over longer in label (unless this is a prefix match where
// longer prefix matches are actually preferred)
if (scoreA < LABEL_PREFIX_SCORE_THRESHOLD && scoreB < LABEL_PREFIX_SCORE_THRESHOLD) {
const comparedByMatchLength = compareByMatchLength(itemScoreA.labelMatch, itemScoreB.labelMatch);
if (comparedByMatchLength !== 0) {
return comparedByMatchLength;
}
}
// prefer shorter labels over longer labels
@@ -650,12 +635,12 @@ export function compareItemsByFuzzyScore<T>(itemA: T, itemB: T, query: IPrepared
}
}
// 5.) compare by score in label+description
// 3.) compare by score in label+description
if (scoreA !== scoreB) {
return scoreA > scoreB ? -1 : 1;
}
// 6.) scores are identical: prefer matches in label over non-label matches
// 4.) scores are identical: prefer matches in label over non-label matches
const itemAHasLabelMatches = Array.isArray(itemScoreA.labelMatch) && itemScoreA.labelMatch.length > 0;
const itemBHasLabelMatches = Array.isArray(itemScoreB.labelMatch) && itemScoreB.labelMatch.length > 0;
if (itemAHasLabelMatches && !itemBHasLabelMatches) {
@@ -664,14 +649,14 @@ export function compareItemsByFuzzyScore<T>(itemA: T, itemB: T, query: IPrepared
return 1;
}
// 7.) scores are identical: prefer more compact matches (label and description)
// 5.) scores are identical: prefer more compact matches (label and description)
const itemAMatchDistance = computeLabelAndDescriptionMatchDistance(itemA, itemScoreA, accessor);
const itemBMatchDistance = computeLabelAndDescriptionMatchDistance(itemB, itemScoreB, accessor);
if (itemAMatchDistance && itemBMatchDistance && itemAMatchDistance !== itemBMatchDistance) {
return itemBMatchDistance > itemAMatchDistance ? -1 : 1;
}
// 8.) scores are identical: start to use the fallback compare
// 6.) scores are identical: start to use the fallback compare
return fallbackCompare(itemA, itemB, query, accessor);
}

View File

@@ -45,7 +45,7 @@ export class MarkdownString implements IMarkdownString {
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
this._value += (this._supportThemeIcons ? escapeCodicons(value) : value)
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
.replace('\n', '\n\n');
.replace(/\n/g, '\n\n');
return this;
}

View File

@@ -5,7 +5,7 @@
import { VSBuffer } from 'vs/base/common/buffer';
import { regExpFlags } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { URI, UriComponents } from 'vs/base/common/uri';
export function stringify(obj: any): string {
return JSON.stringify(obj, replacer);
@@ -33,7 +33,15 @@ function replacer(key: string, value: any): any {
return value;
}
export function revive(obj: any, depth = 0): any {
type Deserialize<T> = T extends UriComponents ? URI
: T extends object
? Revived<T>
: T;
export type Revived<T> = { [K in keyof T]: Deserialize<T[K]> };
export function revive<T = any>(obj: any, depth = 0): Revived<T> {
if (!obj || depth > 200) {
return obj;
}
@@ -41,15 +49,15 @@ export function revive(obj: any, depth = 0): any {
if (typeof obj === 'object') {
switch ((<MarshalledObject>obj).$mid) {
case 1: return URI.revive(obj);
case 2: return new RegExp(obj.source, obj.flags);
case 1: return <any>URI.revive(obj);
case 2: return <any>new RegExp(obj.source, obj.flags);
}
if (
obj instanceof VSBuffer
|| obj instanceof Uint8Array
) {
return obj;
return <any>obj;
}
if (Array.isArray(obj)) {

View File

@@ -33,7 +33,7 @@ export interface ReadableStreamEvents<T> {
/**
* A interface that emulates the API shape of a node.js readable
* stream for use in desktop and web environments.
* stream for use in native and web environments.
*/
export interface ReadableStream<T> extends ReadableStreamEvents<T> {
@@ -60,7 +60,7 @@ export interface ReadableStream<T> extends ReadableStreamEvents<T> {
/**
* A interface that emulates the API shape of a node.js readable
* for use in desktop and web environments.
* for use in native and web environments.
*/
export interface Readable<T> {
@@ -73,7 +73,7 @@ export interface Readable<T> {
/**
* A interface that emulates the API shape of a node.js writeable
* stream for use in desktop and web environments.
* stream for use in native and web environments.
*/
export interface WriteableStream<T> extends ReadableStream<T> {

View File

@@ -258,14 +258,12 @@ export type UriDto<T> = { [K in keyof T]: T[K] extends URI
/**
* Mapped-type that replaces all occurrences of URI with UriComponents and
* drops all functions.
* todo@joh use toJSON-results
*/
export type Dto<T> = { [K in keyof T]: T[K] extends URI
? UriComponents
: T[K] extends Function
? never
: UriDto<T[K]> };
export type Dto<T> = T extends { toJSON(): infer U }
? U
: T extends object
? { [k in keyof T]: Dto<T[k]>; }
: T;
export function NotImplementedProxy<T>(name: string): { new(): T } {
return <any>class {

View File

@@ -93,6 +93,14 @@
process: {
platform: process.platform,
env: process.env,
_whenEnvResolved: undefined,
get whenEnvResolved() {
if (!this._whenEnvResolved) {
this._whenEnvResolved = resolveEnv();
}
return this._whenEnvResolved;
},
on:
/**
* @param {string} type
@@ -157,5 +165,33 @@
return true;
}
/**
* If VSCode is not run from a terminal, we should resolve additional
* shell specific environment from the OS shell to ensure we are seeing
* all development related environment variables. We do this from the
* main process because it may involve spawning a shell.
*/
function resolveEnv() {
return new Promise(function (resolve) {
const handle = setTimeout(function () {
console.warn('Preload: Unable to resolve shell environment in a reasonable time');
// It took too long to fetch the shell environment, return
resolve();
}, 3000);
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
clearTimeout(handle);
// Assign all keys of the shell environment to our process environment
Object.assign(process.env, shellEnv);
resolve();
});
ipcRenderer.send('vscode:fetchShellEnv');
});
}
//#endregion
}());

View File

@@ -84,6 +84,12 @@ export const process = (window as any).vscode.process as {
*/
env: { [key: string]: string | undefined };
/**
* Allows to await resolving the full process environment by checking for the shell environment
* of the OS in certain cases (e.g. when the app is started from the Dock on macOS).
*/
whenEnvResolved: Promise<void>;
/**
* A listener on the process. Only a small subset of listener types are allowed.
*/

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Database, Statement } from 'vscode-sqlite3';
import type { Database, Statement } from 'vscode-sqlite3';
import { Event } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';
import { mapToString, setToString } from 'vs/base/common/map';

View File

@@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import * as assert from 'assert';
suite('renderCodicons', () => {
test('no codicons', () => {
const result = renderCodiconsAsElement(' hello World .');
assert.equal(elementsToString(result), ' hello World .');
});
test('codicon only', () => {
const result = renderCodiconsAsElement('$(alert)');
assert.equal(elementsToString(result), '<span class="codicon codicon-alert"></span>');
});
test('codicon and non-codicon strings', () => {
const result = renderCodiconsAsElement(` $(alert) Unresponsive`);
assert.equal(elementsToString(result), ' <span class="codicon codicon-alert"></span> Unresponsive');
});
test('multiple codicons', () => {
const result = renderCodiconsAsElement('$(check)$(error)');
assert.equal(elementsToString(result), '<span class="codicon codicon-check"></span><span class="codicon codicon-error"></span>');
});
test('escaped codicon', () => {
const result = renderCodiconsAsElement('\\$(escaped)');
assert.equal(elementsToString(result), '$(escaped)');
});
test('codicon with animation', () => {
const result = renderCodiconsAsElement('$(zip~anim)');
assert.equal(elementsToString(result), '<span class="codicon codicon-zip codicon-animation-anim"></span>');
});
const elementsToString = (elements: Array<HTMLElement | string>): string => {
return elements
.map(elem => elem instanceof HTMLElement ? elem.outerHTML : elem)
.reduce((a, b) => a + b, '');
};
});

View File

@@ -688,4 +688,22 @@ suite('Async', () => {
assert.ok(Date.now() - now < 100);
assert.equal(timedout, false);
});
test('SequencerByKey', async () => {
const s = new async.SequencerByKey<string>();
const r1 = await s.queue('key1', () => Promise.resolve('hello'));
assert.equal(r1, 'hello');
await s.queue('key2', () => Promise.reject(new Error('failed'))).then(() => {
throw new Error('should not be resolved');
}, err => {
// Expected error
assert.equal(err.message, 'failed');
});
// Still works after a queued promise is rejected
const r3 = await s.queue('key2', () => Promise.resolve('hello'));
assert.equal(r3, 'hello');
});
});

View File

@@ -57,6 +57,13 @@ suite('Paths', () => {
assert.ok(!extpath.isValidBasename('aux'));
assert.ok(!extpath.isValidBasename('Aux'));
assert.ok(!extpath.isValidBasename('LPT0'));
assert.ok(!extpath.isValidBasename('aux.txt'));
assert.ok(!extpath.isValidBasename('com0.abc'));
assert.ok(extpath.isValidBasename('LPT00'));
assert.ok(extpath.isValidBasename('aux1'));
assert.ok(extpath.isValidBasename('aux1.txt'));
assert.ok(extpath.isValidBasename('aux1.aux.txt'));
assert.ok(!extpath.isValidBasename('test.txt.'));
assert.ok(!extpath.isValidBasename('test.txt..'));
assert.ok(!extpath.isValidBasename('test.txt '));

View File

@@ -1025,6 +1025,51 @@ suite('Fuzzy Scorer', () => {
assert.equal(res[1], resourceB);
});
test('compareFilesByScore - boost better prefix match if multiple queries are used', function () {
const resourceA = URI.file('src/vs/workbench/services/host/browser/browserHostService.ts');
const resourceB = URI.file('src/vs/workbench/browser/workbench.ts');
for (const query of ['workbench.ts browser', 'browser workbench.ts', 'browser workbench', 'workbench browser']) {
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
}
});
test('compareFilesByScore - boost shorter prefix match if multiple queries are used', function () {
const resourceA = URI.file('src/vs/workbench/browser/actions/windowActions.ts');
const resourceB = URI.file('src/vs/workbench/electron-browser/window.ts');
for (const query of ['window browser', 'window.ts browser']) {
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
}
});
test('compareFilesByScore - boost shorter prefix match if multiple queries are used (#99171)', function () {
const resourceA = URI.file('mesh_editor_lifetime_job.h');
const resourceB = URI.file('lifetime_job.h');
for (const query of ['m life, life m']) {
let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
res = [resourceB, resourceA].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor));
assert.equal(res[0], resourceB);
assert.equal(res[1], resourceA);
}
});
test('prepareQuery', () => {
assert.equal(scorer.prepareQuery(' f*a ').normalized, 'fa');
assert.equal(scorer.prepareQuery('model Tester.ts').original, 'model Tester.ts');

View File

@@ -17,6 +17,9 @@
<!-- Builtin Extensions (running out of sources) -->
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
<!-- Workbench Credentials (running out of sources) -->
<meta id="vscode-workbench-credentials" data-settings="{{WORKBENCH_CREDENTIALS}}">
<!-- Workarounds/Hacks (remote user data uri) -->
<meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}">

View File

@@ -3,8 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchConstructionOptions, create, ICredentialsProvider, IURLCallbackProvider, IWorkspaceProvider, IWorkspace, IWindowIndicator, ICommand, IHomeIndicator, IProductQualityChangeHandler } from 'vs/workbench/workbench.web.api';
import product from 'vs/platform/product/common/product';
import { IWorkbenchConstructionOptions, create, ICredentialsProvider, IURLCallbackProvider, IWorkspaceProvider, IWorkspace, IWindowIndicator, IHomeIndicator, IProductQualityChangeHandler } from 'vs/workbench/workbench.web.api';
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { generateUuid } from 'vs/base/common/uuid';
@@ -16,6 +15,7 @@ import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/wi
import { isEqual } from 'vs/base/common/resources';
import { isStandalone } from 'vs/base/browser/browser';
import { localize } from 'vs/nls';
import { Schemas } from 'vs/base/common/network';
interface ICredential {
service: string;
@@ -27,6 +27,13 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider {
static readonly CREDENTIALS_OPENED_KEY = 'credentials.provider';
constructor(credentials: ICredential[]) {
this._credentials = credentials;
for (const { service, account, password } of this._credentials) {
this.setPassword(service, account, password);
}
}
private _credentials: ICredential[] | undefined;
private get credentials(): ICredential[] {
if (!this._credentials) {
@@ -277,6 +284,20 @@ class WorkspaceProvider implements IWorkspaceProvider {
return false;
}
hasRemote(): boolean {
if (this.workspace) {
if (isFolderToOpen(this.workspace)) {
return this.workspace.folderUri.scheme === Schemas.vscodeRemote;
}
if (isWorkspaceToOpen(this.workspace)) {
return this.workspace.workspaceUri.scheme === Schemas.vscodeRemote;
}
}
return true;
}
}
class WindowIndicator implements IWindowIndicator {
@@ -287,8 +308,6 @@ class WindowIndicator implements IWindowIndicator {
readonly tooltip: string;
readonly command: string | undefined;
readonly commandImpl: ICommand | undefined = undefined;
constructor(workspace: IWorkspace) {
let repositoryOwner: string | undefined = undefined;
let repositoryName: string | undefined = undefined;
@@ -306,20 +325,16 @@ class WindowIndicator implements IWindowIndicator {
}
}
// Repo
if (repositoryName && repositoryOwner) {
this.label = localize('openInDesktopLabel', "$(remote) Open in Desktop");
this.tooltip = localize('openInDesktopTooltip', "Open in Desktop");
this.command = '_web.openInDesktop';
this.commandImpl = {
id: this.command,
handler: () => {
const protocol = product.quality === 'stable' ? 'vscode' : 'vscode-insiders';
window.open(`${protocol}://vscode.git/clone?url=${encodeURIComponent(`https://github.com/${repositoryOwner}/${repositoryName}.git`)}`);
}
};
} else {
this.label = localize('playgroundLabel', "Web Playground");
this.tooltip = this.label;
this.label = localize('playgroundLabelRepository', "$(remote) VS Code Web Playground: {0}/{1}", repositoryOwner, repositoryName);
this.tooltip = localize('playgroundRepositoryTooltip', "VS Code Web Playground: {0}/{1}", repositoryOwner, repositoryName);
}
// No Repo
else {
this.label = localize('playgroundLabel', "$(remote) VS Code Web Playground");
this.tooltip = localize('playgroundTooltip', "VS Code Web Playground");
}
}
}
@@ -391,6 +406,9 @@ class WindowIndicator implements IWindowIndicator {
}
}
// Workspace Provider
const workspaceProvider = new WorkspaceProvider(workspace, payload);
// Home Indicator
const homeIndicator: IHomeIndicator = {
href: 'https://github.com/Microsoft/vscode',
@@ -398,13 +416,10 @@ class WindowIndicator implements IWindowIndicator {
title: localize('home', "Home")
};
// Commands
const commands: ICommand[] = [];
// Window indicator
const windowIndicator = new WindowIndicator(workspace);
if (windowIndicator.commandImpl) {
commands.push(windowIndicator.commandImpl);
// Window indicator (unless connected to a remote)
let windowIndicator: WindowIndicator | undefined = undefined;
if (!workspaceProvider.hasRemote()) {
windowIndicator = new WindowIndicator(workspace);
}
// Product Quality Change Handler
@@ -422,15 +437,19 @@ class WindowIndicator implements IWindowIndicator {
window.location.href = `${window.location.origin}?${queryString}`;
};
// Find credentials from DOM
const credentialsElement = document.getElementById('vscode-workbench-credentials');
const credentialsElementAttribute = credentialsElement ? credentialsElement.getAttribute('data-settings') : undefined;
const credentialsProvider = new LocalStorageCredentialsProvider(credentialsElementAttribute ? JSON.parse(credentialsElementAttribute) : []);
// Finally create workbench
create(document.body, {
...config,
homeIndicator,
commands,
windowIndicator,
productQualityChangeHandler,
workspaceProvider: new WorkspaceProvider(workspace, payload),
workspaceProvider,
urlCallbackProvider: new PollingURLCallbackProvider(),
credentialsProvider: new LocalStorageCredentialsProvider()
credentialsProvider
});
})();

View File

@@ -33,8 +33,8 @@ const bootstrapWindow = (() => {
return window.MonacoBootstrapWindow;
})();
// Setup shell environment
process['lazyEnv'] = getLazyEnv();
// Load environment in parallel to workbench loading to avoid waterfall
const whenEnvResolved = bootstrapWindow.globals().process.whenEnvResolved;
// Load workbench main JS, CSS and NLS all in parallel. This is an
// optimization to prevent a waterfall of loading to happen, because
@@ -46,18 +46,19 @@ bootstrapWindow.load([
'vs/nls!vs/workbench/workbench.desktop.main',
'vs/css!vs/workbench/workbench.desktop.main'
],
function (workbench, configuration) {
async function (workbench, configuration) {
// Mark start of workbench
perf.mark('didLoadWorkbenchMain');
performance.mark('workbench-start');
return process['lazyEnv'].then(function () {
perf.mark('main/startup');
// Wait for process environment being fully resolved
await whenEnvResolved;
// @ts-ignore
return require('vs/workbench/electron-browser/desktop.main').main(configuration);
});
perf.mark('main/startup');
// @ts-ignore
return require('vs/workbench/electron-browser/desktop.main').main(configuration);
},
{
removeDeveloperKeybindingsAfterLoad: true,
@@ -77,7 +78,7 @@ bootstrapWindow.load([
* @param {{
* partsSplashPath?: string,
* highContrast?: boolean,
* defaultThemeType?: string,
* autoDetectHighContrast?: boolean,
* extensionDevelopmentPath?: string[],
* folderUri?: object,
* workspace?: object
@@ -96,7 +97,8 @@ function showPartsSplash(configuration) {
}
// high contrast mode has been turned on from the outside, e.g. OS -> ignore stored colors and layouts
if (data && configuration.highContrast && data.baseTheme !== 'hc-black') {
const isHighContrast = configuration.highContrast && configuration.autoDetectHighContrast;
if (data && isHighContrast && data.baseTheme !== 'hc-black') {
data = undefined;
}
@@ -111,14 +113,10 @@ function showPartsSplash(configuration) {
baseTheme = data.baseTheme;
shellBackground = data.colorInfo.editorBackground;
shellForeground = data.colorInfo.foreground;
} else if (configuration.highContrast || configuration.defaultThemeType === 'hc') {
} else if (isHighContrast) {
baseTheme = 'hc-black';
shellBackground = '#000000';
shellForeground = '#FFFFFF';
} else if (configuration.defaultThemeType === 'vs') {
baseTheme = 'vs';
shellBackground = '#FFFFFF';
shellForeground = '#000000';
} else {
baseTheme = 'vs-dark';
shellBackground = '#1E1E1E';
@@ -172,26 +170,3 @@ function showPartsSplash(configuration) {
perf.mark('didShowPartsSplash');
}
/**
* @returns {Promise<void>}
*/
function getLazyEnv() {
const ipcRenderer = bootstrapWindow.globals().ipcRenderer;
return new Promise(function (resolve) {
const handle = setTimeout(function () {
resolve();
console.warn('renderer did not receive lazyEnv in time');
}, 10000);
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
clearTimeout(handle);
Object.assign(process.env, shellEnv);
// @ts-ignore
resolve(process.env);
});
ipcRenderer.send('vscode:fetchShellEnv');
});
}

View File

@@ -50,7 +50,7 @@ import { setUnexpectedErrorHandler, onUnexpectedError } from 'vs/base/common/err
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { RunOnceScheduler, timeout } from 'vs/base/common/async';
import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu';
import { homedir } from 'os';
import { join, sep, posix } from 'vs/base/common/path';
@@ -68,11 +68,11 @@ import { statSync } from 'fs';
import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsIpc';
import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService';
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
import { ElectronExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/electron-main/extensionHostDebugIpc';
import { IElectronMainService, ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService';
import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
import { withNullAsUndefined } from 'vs/base/common/types';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { coalesce } from 'vs/base/common/arrays';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { StorageKeysSyncRegistryChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
@@ -80,8 +80,6 @@ import { INativeEnvironmentService } from 'vs/platform/environment/node/environm
import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels';
import { WebviewMainService } from 'vs/platform/webview/electron-main/webviewMainService';
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
import { createServer, AddressInfo } from 'net';
import { IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { IFileService } from 'vs/platform/files/common/files';
import { stripComments } from 'vs/base/common/json';
import { generateUuid } from 'vs/base/common/uuid';
@@ -272,6 +270,12 @@ export class CodeApplication extends Disposable {
try {
const shellEnv = await getShellEnvironment(this.logService, this.environmentService);
// TODO@sandbox workaround for https://github.com/electron/electron/issues/25119
if (this.environmentService.sandbox) {
await timeout(100);
}
if (!webContents.isDestroyed()) {
webContents.send('vscode:acceptShellEnv', shellEnv);
}
@@ -297,7 +301,7 @@ export class CodeApplication extends Disposable {
const nativeKeymap = await import('native-keymap');
nativeKeymap.onDidChangeKeyboardLayout(() => {
if (this.windowsMainService) {
this.windowsMainService.sendToAll('vscode:keyboardLayoutChanged', false);
this.windowsMainService.sendToAll('vscode:keyboardLayoutChanged');
}
});
})();
@@ -364,17 +368,17 @@ export class CodeApplication extends Disposable {
const sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId, this.userEnv);
const sharedProcessClient = sharedProcess.whenIpcReady().then(() => {
this.logService.trace('Shared process: IPC ready');
return connect(this.environmentService.sharedIPCHandle, 'main');
});
const sharedProcessReady = sharedProcess.whenReady().then(() => {
this.logService.trace('Shared process: init ready');
return sharedProcessClient;
});
this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => {
this._register(new RunOnceScheduler(async () => {
const userEnv = await getShellEnvironment(this.logService, this.environmentService);
sharedProcess.spawn(userEnv);
sharedProcess.spawn(await getShellEnvironment(this.logService, this.environmentService));
}, 3000)).schedule();
});
@@ -847,6 +851,9 @@ export class CodeApplication extends Disposable {
} catch (error) {
this.logService.error(error);
}
// Start to fetch shell environment after window has opened
getShellEnvironment(this.logService, this.environmentService);
}
private handleRemoteAuthorities(): void {
@@ -858,100 +865,3 @@ export class CodeApplication extends Disposable {
});
}
}
class ElectronExtensionHostDebugBroadcastChannel<TContext> extends ExtensionHostDebugBroadcastChannel<TContext> {
constructor(private windowsMainService: IWindowsMainService) {
super();
}
call(ctx: TContext, command: string, arg?: any): Promise<any> {
if (command === 'openExtensionDevelopmentHostWindow') {
return this.openExtensionDevelopmentHostWindow(arg[0], arg[1], arg[2]);
} else {
return super.call(ctx, command, arg);
}
}
private async openExtensionDevelopmentHostWindow(args: string[], env: IProcessEnvironment, debugRenderer: boolean): Promise<IOpenExtensionWindowResult> {
const pargs = parseArgs(args, OPTIONS);
const extDevPaths = pargs.extensionDevelopmentPath;
if (!extDevPaths) {
return {};
}
const [codeWindow] = this.windowsMainService.openExtensionDevelopmentHostWindow(extDevPaths, {
context: OpenContext.API,
cli: pargs,
userEnv: Object.keys(env).length > 0 ? env : undefined
});
if (!debugRenderer) {
return {};
}
const debug = codeWindow.win.webContents.debugger;
let listeners = debug.isAttached() ? Infinity : 0;
const server = createServer(listener => {
if (listeners++ === 0) {
debug.attach();
}
let closed = false;
const writeMessage = (message: object) => {
if (!closed) { // in case sendCommand promises settle after closed
listener.write(JSON.stringify(message) + '\0'); // null-delimited, CDP-compatible
}
};
const onMessage = (_event: Event, method: string, params: unknown, sessionId?: string) =>
writeMessage(({ method, params, sessionId }));
codeWindow.win.on('close', () => {
debug.removeListener('message', onMessage);
listener.end();
closed = true;
});
debug.addListener('message', onMessage);
let buf = Buffer.alloc(0);
listener.on('data', data => {
buf = Buffer.concat([buf, data]);
for (let delimiter = buf.indexOf(0); delimiter !== -1; delimiter = buf.indexOf(0)) {
let data: { id: number; sessionId: string; params: {} };
try {
const contents = buf.slice(0, delimiter).toString('utf8');
buf = buf.slice(delimiter + 1);
data = JSON.parse(contents);
} catch (e) {
console.error('error reading cdp line', e);
}
// depends on a new API for which electron.d.ts has not been updated:
// @ts-ignore
debug.sendCommand(data.method, data.params, data.sessionId)
.then((result: object) => writeMessage({ id: data.id, sessionId: data.sessionId, result }))
.catch((error: Error) => writeMessage({ id: data.id, sessionId: data.sessionId, error: { code: 0, message: error.message } }));
}
});
listener.on('error', err => {
console.error('error on cdp pipe:', err);
});
listener.on('close', () => {
closed = true;
if (--listeners === 0) {
debug.detach();
}
});
});
await new Promise(r => server.listen(0, r));
codeWindow.win.on('close', () => server.close());
return { rendererDebugPort: (server.address() as AddressInfo).port };
}
}

View File

@@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects';
import * as nls from 'vs/nls';
import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event } from 'electron';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme, Event, Details } from 'electron';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { ILogService } from 'vs/platform/log/common/log';
@@ -167,12 +167,23 @@ export class CodeWindow extends Disposable implements ICodeWindow {
title: product.nameLong,
webPreferences: {
preload: URI.parse(this.doGetPreloadUrl()).fsPath,
nodeIntegration: true,
enableWebSQL: false,
enableRemoteModule: false,
nativeWindowOpen: true,
webviewTag: true,
zoomFactor: zoomLevelToZoomFactor(windowConfig?.zoomLevel)
zoomFactor: zoomLevelToZoomFactor(windowConfig?.zoomLevel),
...this.environmentService.sandbox ?
// Sandbox
{
sandbox: true,
contextIsolation: true
} :
// No Sandbox
{
nodeIntegration: true
}
}
};
@@ -325,7 +336,18 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return !!this.documentEdited;
}
focus(): void {
focus(options?: { force: boolean }): void {
// macOS: Electron >6.x changed its behaviour to not
// bring the application to the foreground when a window
// is focused programmatically. Only via `app.focus` and
// the option `steal: true` can you get the previous
// behaviour back. The only reason to use this option is
// when a window is getting focused while the application
// is not in the foreground.
if (isMacintosh && options?.force) {
app.focus({ steal: true });
}
if (!this._win) {
return;
}
@@ -392,7 +414,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private registerListeners(): void {
// Crashes & Unrsponsive
this._win.webContents.on('crashed', () => this.onWindowError(WindowError.CRASHED));
this._win.webContents.on('render-process-gone', (event, details) => this.onWindowError(WindowError.CRASHED, details));
this._win.on('unresponsive', () => this.onWindowError(WindowError.UNRESPONSIVE));
// Window close
@@ -524,8 +546,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: Object.assign(details.requestHeaders, headers) })));
}
private onWindowError(error: WindowError): void {
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: renderer process crashed!' : '[VS Code]: detected unresponsive');
private onWindowError(error: WindowError.UNRESPONSIVE): void;
private onWindowError(error: WindowError.CRASHED, details: Details): void;
private onWindowError(error: WindowError, details?: Details): void {
this.logService.error(error === WindowError.CRASHED ? `[VS Code]: renderer process crashed (detail: ${details?.reason})` : '[VS Code]: detected unresponsive');
// If we run extension tests from CLI, showing a dialog is not
// very helpful in this case. Rather, we bring down the test run
@@ -579,11 +603,18 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Crashed
else {
let message: string;
if (details && details.reason !== 'crashed') {
message = nls.localize('appCrashedDetails', "The window has crashed (reason: '{0}')", details?.reason);
} else {
message = nls.localize('appCrashed', "The window has crashed", details?.reason);
}
this.dialogMainService.showMessageBox({
title: product.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(nls.localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(nls.localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message: nls.localize('appCrashed', "The window has crashed"),
message,
detail: nls.localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."),
noLink: true
}, this._win).then(result => {
@@ -699,7 +730,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.showTimeoutHandle = setTimeout(() => {
if (this._win && !this._win.isVisible() && !this._win.isMinimized()) {
this._win.show();
this._win.focus();
this.focus({ force: true });
this._win.webContents.openDevTools();
}
}, 10000);
@@ -754,11 +785,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
windowConfiguration.fullscreen = this.isFullScreen;
// Set Accessibility Config
let autoDetectHighContrast = true;
if (windowConfig?.autoDetectHighContrast === false) {
autoDetectHighContrast = false;
}
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && nativeTheme.shouldUseInvertedColorScheme;
windowConfiguration.highContrast = nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors;
windowConfiguration.autoDetectHighContrast = windowConfig?.autoDetectHighContrast ?? true;
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;
// Title style related
@@ -799,7 +827,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
private doGetUrl(config: object): string {
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
let workbench: string;
if (this.environmentService.sandbox) {
workbench = 'vs/code/electron-sandbox/workbench/workbench.html';
} else {
workbench = 'vs/code/electron-browser/workbench/workbench.html';
}
return `${require.toUrl(workbench)}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
private doGetPreloadUrl(): string {

View File

@@ -8,7 +8,7 @@ import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { ipcRenderer, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
import { $, windowOpenNoOpener, addClass } from 'vs/base/browser/dom';
import { $, reset, windowOpenNoOpener, addClass } from 'vs/base/browser/dom';
import { Button } from 'vs/base/browser/ui/button/button';
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
import * as collections from 'vs/base/common/collections';
@@ -277,33 +277,25 @@ export class IssueReporter extends Disposable {
}
private updateSettingsSearchDetails(data: ISettingsSearchIssueReporterData): void {
const target = document.querySelector('.block-settingsSearchResults .block-info');
const target = document.querySelector<HTMLElement>('.block-settingsSearchResults .block-info');
if (target) {
const details = `
<div class='block-settingsSearchResults-details'>
<div>Query: "${data.query}"</div>
<div>Literal match count: ${data.filterResultCount}</div>
</div>
`;
const queryDiv = $<HTMLDivElement>('div', undefined, `Query: "${data.query}"` as string);
const countDiv = $<HTMLElement>('div', undefined, `Literal match count: ${data.filterResultCount}` as string);
const detailsDiv = $<HTMLDivElement>('.block-settingsSearchResults-details', undefined, queryDiv, countDiv);
let table = `
<tr>
<th>Setting</th>
<th>Extension</th>
<th>Score</th>
</tr>`;
data.actualSearchResults
.forEach(setting => {
table += `
<tr>
<td>${setting.key}</td>
<td>${setting.extensionId}</td>
<td>${String(setting.score).slice(0, 5)}</td>
</tr>`;
});
target.innerHTML = `${details}<table>${table}</table>`;
const table = $('table', undefined,
$('tr', undefined,
$('th', undefined, 'Setting'),
$('th', undefined, 'Extension'),
$('th', undefined, 'Score'),
),
...data.actualSearchResults.map(setting => $('tr', undefined,
$('td', undefined, setting.key),
$('td', undefined, setting.extensionId),
$('td', undefined, String(setting.score).slice(0, 5)),
))
);
reset(target, detailsDiv, table);
}
}
@@ -654,9 +646,9 @@ export class IssueReporter extends Disposable {
issueState.appendChild(issueIcon);
issueState.appendChild(issueStateLabel);
item = $('div.issue', {}, issueState, link);
item = $('div.issue', undefined, issueState, link);
} else {
item = $('div.issue', {}, link);
item = $('div.issue', undefined, link);
}
issues.appendChild(item);
@@ -672,19 +664,19 @@ export class IssueReporter extends Disposable {
}
private setUpTypes(): void {
const makeOption = (issueType: IssueType, description: string) => `<option value="${issueType.valueOf()}">${escape(description)}</option>`;
const makeOption = (issueType: IssueType, description: string) => $('option', { 'value': issueType.valueOf() }, escape(description));
const typeSelect = this.getElementById('issue-type')! as HTMLSelectElement;
const { issueType } = this.issueReporterModel.getData();
if (issueType === IssueType.SettingsSearchIssue) {
typeSelect.innerHTML = makeOption(IssueType.SettingsSearchIssue, localize('settingsSearchIssue', "Settings Search Issue"));
reset(typeSelect, makeOption(IssueType.SettingsSearchIssue, localize('settingsSearchIssue', "Settings Search Issue")));
typeSelect.disabled = true;
} else {
typeSelect.innerHTML = [
reset(typeSelect,
makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")),
makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")),
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue"))
].join('\n');
);
}
typeSelect.value = issueType.toString();
@@ -774,9 +766,8 @@ export class IssueReporter extends Disposable {
} else {
show(extensionsBlock);
}
descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} <span class="required-input">*</span>`;
descriptionSubtitle.innerHTML = localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce"), $('span.required-input', undefined, '*'));
reset(descriptionSubtitle, localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
} else if (issueType === IssueType.PerformanceIssue) {
show(blockContainer);
show(systemBlock);
@@ -790,11 +781,11 @@ export class IssueReporter extends Disposable {
show(extensionsBlock);
}
descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} <span class="required-input">*</span>`;
descriptionSubtitle.innerHTML = localize('performanceIssueDesciption', "When did this performance issue happen? Does it occur on startup or after a specific series of actions? We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce"), $('span.required-input', undefined, '*'));
reset(descriptionSubtitle, localize('performanceIssueDesciption', "When did this performance issue happen? Does it occur on startup or after a specific series of actions? We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
} else if (issueType === IssueType.FeatureRequest) {
descriptionTitle.innerHTML = `${localize('description', "Description")} <span class="required-input">*</span>`;
descriptionSubtitle.innerHTML = localize('featureRequestDescription', "Please describe the feature you would like to see. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
reset(descriptionTitle, localize('description', "Description"), $('span.required-input', undefined, '*'));
reset(descriptionSubtitle, localize('featureRequestDescription', "Please describe the feature you would like to see. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
show(problemSource);
if (fileOnExtension) {
@@ -805,8 +796,8 @@ export class IssueReporter extends Disposable {
show(searchedExtensionsBlock);
show(settingsSearchResultsBlock);
descriptionTitle.innerHTML = `${localize('expectedResults', "Expected Results")} <span class="required-input">*</span>`;
descriptionSubtitle.innerHTML = localize('settingsSearchResultsDescription', "Please list the results that you were expecting to see when you searched with this query. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.");
reset(descriptionTitle, localize('expectedResults', "Expected Results"), $('span.required-input', undefined, '*'));
reset(descriptionSubtitle, localize('settingsSearchResultsDescription', "Please list the results that you were expecting to see when you searched with this query. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
}
}
@@ -928,42 +919,82 @@ export class IssueReporter extends Disposable {
}
private updateSystemInfo(state: IssueReporterModelData) {
const target = document.querySelector('.block-system .block-info');
const target = document.querySelector<HTMLElement>('.block-system .block-info');
if (target) {
const systemInfo = state.systemInfo!;
let renderedData = `
<table>
<tr><td>CPUs</td><td>${systemInfo.cpus}</td></tr>
<tr><td>GPU Status</td><td>${Object.keys(systemInfo.gpuStatus).map(key => `${key}: ${systemInfo.gpuStatus[key]}`).join('<br>')}</td></tr>
<tr><td>Load (avg)</td><td>${systemInfo.load}</td></tr>
<tr><td>Memory (System)</td><td>${systemInfo.memory}</td></tr>
<tr><td>Process Argv</td><td>${systemInfo.processArgs}</td></tr>
<tr><td>Screen Reader</td><td>${systemInfo.screenReader}</td></tr>
<tr><td>VM</td><td>${systemInfo.vmHint}</td></tr>
</table>`;
const renderedDataTable = $('table', undefined,
$('tr', undefined,
$('td', undefined, 'CPUs'),
$('td', undefined, systemInfo.cpus || ''),
),
$('tr', undefined,
$('td', undefined, 'GPU Status' as string),
$('td', undefined, Object.keys(systemInfo.gpuStatus).map(key => `${key}: ${systemInfo.gpuStatus[key]}`).join('\n')),
),
$('tr', undefined,
$('td', undefined, 'Load (avg)' as string),
$('td', undefined, systemInfo.load || ''),
),
$('tr', undefined,
$('td', undefined, 'Memory (System)' as string),
$('td', undefined, systemInfo.memory),
),
$('tr', undefined,
$('td', undefined, 'Process Argv' as string),
$('td', undefined, systemInfo.processArgs),
),
$('tr', undefined,
$('td', undefined, 'Screen Reader' as string),
$('td', undefined, systemInfo.screenReader),
),
$('tr', undefined,
$('td', undefined, 'VM'),
$('td', undefined, systemInfo.vmHint),
),
);
reset(target, renderedDataTable);
systemInfo.remoteData.forEach(remote => {
target.appendChild($<HTMLHRElement>('hr'));
if (isRemoteDiagnosticError(remote)) {
renderedData += `
<hr>
<table>
<tr><td>Remote</td><td>${remote.hostName}</td></tr>
<tr><td></td><td>${remote.errorMessage}</td></tr>
</table>`;
const remoteDataTable = $('table', undefined,
$('tr', undefined,
$('td', undefined, 'Remote'),
$('td', undefined, remote.hostName)
),
$('tr', undefined,
$('td', undefined, ''),
$('td', undefined, remote.errorMessage)
)
);
target.appendChild(remoteDataTable);
} else {
renderedData += `
<hr>
<table>
<tr><td>Remote</td><td>${remote.hostName}</td></tr>
<tr><td>OS</td><td>${remote.machineInfo.os}</td></tr>
<tr><td>CPUs</td><td>${remote.machineInfo.cpus}</td></tr>
<tr><td>Memory (System)</td><td>${remote.machineInfo.memory}</td></tr>
<tr><td>VM</td><td>${remote.machineInfo.vmHint}</td></tr>
</table>`;
const remoteDataTable = $('table', undefined,
$('tr', undefined,
$('td', undefined, 'Remote'),
$('td', undefined, remote.hostName)
),
$('tr', undefined,
$('td', undefined, 'OS'),
$('td', undefined, remote.machineInfo.os)
),
$('tr', undefined,
$('td', undefined, 'CPUs'),
$('td', undefined, remote.machineInfo.cpus || '')
),
$('tr', undefined,
$('td', undefined, 'Memory (System)' as string),
$('td', undefined, remote.machineInfo.memory)
),
$('tr', undefined,
$('td', undefined, 'VM'),
$('td', undefined, remote.machineInfo.vmHint)
),
);
target.appendChild(remoteDataTable);
}
});
target.innerHTML = renderedData;
}
}
@@ -995,15 +1026,18 @@ export class IssueReporter extends Disposable {
return 0;
});
const makeOption = (extension: IOption, selectedExtension?: IssueReporterExtensionData) => {
const makeOption = (extension: IOption, selectedExtension?: IssueReporterExtensionData): HTMLOptionElement => {
const selected = selectedExtension && extension.id === selectedExtension.id;
return `<option value="${extension.id}" ${selected ? 'selected' : ''}>${escape(extension.name)}</option>`;
return $<HTMLOptionElement>('option', {
'value': extension.id,
'selected': selected || ''
}, extension.name);
};
const extensionsSelector = this.getElementById('extension-selector');
if (extensionsSelector) {
const { selectedExtension } = this.issueReporterModel.getData();
extensionsSelector.innerHTML = '<option></option>' + extensionOptions.map(extension => makeOption(extension, selectedExtension)).join('\n');
reset(extensionsSelector, $<HTMLOptionElement>('option'), ...extensionOptions.map(extension => makeOption(extension, selectedExtension)));
this.addEventListener('extension-selector', 'change', (e: Event) => {
const selectedExtensionId = (<HTMLInputElement>e.target).value;
@@ -1071,9 +1105,9 @@ export class IssueReporter extends Disposable {
}
private updateProcessInfo(state: IssueReporterModelData) {
const target = document.querySelector('.block-process .block-info');
const target = document.querySelector('.block-process .block-info') as HTMLElement;
if (target) {
target.innerHTML = `<code>${state.processInfo}</code>`;
reset(target, $('code', undefined, state.processInfo));
}
}
@@ -1085,7 +1119,7 @@ export class IssueReporter extends Disposable {
const target = document.querySelector<HTMLElement>('.block-extensions .block-info');
if (target) {
if (this.configuration.disableExtensions) {
target.innerHTML = localize('disabledExtensions', "Extensions are disabled");
reset(target, localize('disabledExtensions', "Extensions are disabled"));
return;
}
@@ -1097,8 +1131,7 @@ export class IssueReporter extends Disposable {
return;
}
const table = this.getExtensionTableHtml(extensions);
target.innerHTML = `<table>${table}</table>${themeExclusionStr}`;
reset(target, this.getExtensionTableHtml(extensions), document.createTextNode(themeExclusionStr));
}
}
@@ -1111,28 +1144,24 @@ export class IssueReporter extends Disposable {
}
const table = this.getExtensionTableHtml(extensions);
target.innerHTML = `<table>${table}</table>`;
target.innerText = '';
target.appendChild(table);
}
}
private getExtensionTableHtml(extensions: IssueReporterExtensionData[]): string {
let table = `
<tr>
<th>Extension</th>
<th>Author (truncated)</th>
<th>Version</th>
</tr>`;
table += extensions.map(extension => {
return `
<tr>
<td>${extension.name}</td>
<td>${extension.publisher.substr(0, 3)}</td>
<td>${extension.version}</td>
</tr>`;
}).join('');
return table;
private getExtensionTableHtml(extensions: IssueReporterExtensionData[]): HTMLTableElement {
return $('table', undefined,
$('tr', undefined,
$('th', undefined, 'Extension'),
$('th', undefined, 'Author (truncated)' as string),
$('th', undefined, 'Version'),
),
...extensions.map(extension => $('tr', undefined,
$('td', undefined, extension.name),
$('td', undefined, extension.publisher.substr(0, 3)),
$('td', undefined, extension.version),
))
);
}
private openLink(event: MouseEvent): void {

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#646465" d="M6 4v8l4-4-4-4zm1 2.414L8.586 8 7 9.586V6.414z"/></svg>

Before

Width:  |  Height:  |  Size: 139 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#646465" d="M11 10H5.344L11 4.414V10z"/></svg>

Before

Width:  |  Height:  |  Size: 118 B

View File

@@ -58,6 +58,7 @@ table {
width: 100%;
table-layout: fixed;
}
th[scope='col'] {
vertical-align: bottom;
border-bottom: 1px solid #cccccc;
@@ -65,6 +66,7 @@ th[scope='col'] {
border-top: 1px solid #cccccc;
cursor: default;
}
td {
padding: .25rem;
vertical-align: top;
@@ -100,7 +102,6 @@ tbody > tr:hover {
display: none;
}
img {
width: 16px;
margin-right: 4px;
.header {
display: flex;
}

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/processExplorer';
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { localize } from 'vs/nls';
@@ -16,6 +17,7 @@ import { addDisposableListener, addClass } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/;
const DEBUG_PORT_PATTERN = /\s--(inspect|debug)-port=(\d+)/;
@@ -156,15 +158,15 @@ class ProcessExplorer {
return maxProcessId;
}
private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: HTMLImageElement, sectionName: string) {
private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: CodiconLabel, sectionName: string) {
if (shouldExpand) {
body.classList.remove('hidden');
this.collapsedStateCache.set(sectionName, false);
twistie.src = './media/expanded.svg';
twistie.text = '$(chevron-down)';
} else {
body.classList.add('hidden');
this.collapsedStateCache.set(sectionName, true);
twistie.src = './media/collapsed.svg';
twistie.text = '$(chevron-right)';
}
}
@@ -191,18 +193,27 @@ class ProcessExplorer {
private renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) {
const headerRow = document.createElement('tr');
const data = document.createElement('td');
data.textContent = sectionName;
data.colSpan = 4;
headerRow.appendChild(data);
const twistie = document.createElement('img');
this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistie, sectionName);
data.prepend(twistie);
const headerData = document.createElement('td');
headerData.colSpan = 4;
headerRow.appendChild(headerData);
this.listeners.add(addDisposableListener(data, 'click', (e) => {
const headerContainer = document.createElement('div');
headerContainer.className = 'header';
headerData.appendChild(headerContainer);
const twistieContainer = document.createElement('div');
const twistieCodicon = new CodiconLabel(twistieContainer);
this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistieCodicon, sectionName);
headerContainer.appendChild(twistieContainer);
const headerLabel = document.createElement('span');
headerLabel.textContent = sectionName;
headerContainer.appendChild(headerLabel);
this.listeners.add(addDisposableListener(headerData, 'click', (e) => {
const isHidden = body.classList.contains('hidden');
this.updateSectionCollapsedState(isHidden, body, twistie, sectionName);
this.updateSectionCollapsedState(isHidden, body, twistieCodicon, sectionName);
}));
container.appendChild(headerRow);

View File

@@ -0,0 +1,18 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https: vscode-remote-resource:;">
</head>
<body aria-label="">
</body>
<!-- Init Bootstrap Helpers -->
<script src="../../../../bootstrap.js"></script>
<script src="../../../../vs/loader.js"></script>
<script src="../../../../bootstrap-window.js"></script>
<!-- Startup via workbench.js -->
<script src="workbench.js"></script>
</html>

View File

@@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path="../../../../typings/require.d.ts" />
//@ts-check
'use strict';
const perf = (function () {
globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || [];
return {
/**
* @param {string} name
*/
mark(name) {
globalThis.MonacoPerformanceMarks.push(name, Date.now());
}
};
})();
perf.mark('renderer/started');
/**
* @type {{
* load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown,
* globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals')
* }}
*/
const bootstrapWindow = (() => {
// @ts-ignore (defined in bootstrap-window.js)
return window.MonacoBootstrapWindow;
})();
// Load environment in parallel to workbench loading to avoid waterfall
const whenEnvResolved = bootstrapWindow.globals().process.whenEnvResolved;
// Load workbench main JS, CSS and NLS all in parallel. This is an
// optimization to prevent a waterfall of loading to happen, because
// we know for a fact that workbench.desktop.sandbox.main will depend on
// the related CSS and NLS counterparts.
bootstrapWindow.load([
'vs/workbench/workbench.desktop.sandbox.main',
'vs/nls!vs/workbench/workbench.desktop.main',
'vs/css!vs/workbench/workbench.desktop.main'
],
async function (workbench, configuration) {
// Mark start of workbench
perf.mark('didLoadWorkbenchMain');
performance.mark('workbench-start');
// Wait for process environment being fully resolved
await whenEnvResolved;
perf.mark('main/startup');
// @ts-ignore
return require('vs/workbench/electron-sandbox/desktop.main').main(configuration);
},
{
removeDeveloperKeybindingsAfterLoad: true,
canModifyDOM: function (windowConfig) {
// TODO@sandbox part-splash is non-sandboxed only
},
beforeLoaderConfig: function (windowConfig, loaderConfig) {
loaderConfig.recordStats = true;
},
beforeRequire: function () {
perf.mark('willLoadWorkbenchMain');
}
}
);

View File

@@ -14,7 +14,7 @@ import * as paths from 'vs/base/common/path';
import { whenDeleted, writeFileSync } from 'vs/base/node/pfs';
import { findFreePort, randomPort } from 'vs/base/node/ports';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { ProfilingSession, Target } from 'v8-inspect-profiler';
import type { ProfilingSession, Target } from 'v8-inspect-profiler';
import { isString } from 'vs/base/common/types';
import { hasStdinWithoutTty, stdinDataListener, getStdinFilePath, readFromStdin } from 'vs/platform/environment/node/stdin';

View File

@@ -7,7 +7,6 @@ import { localize } from 'vs/nls';
import { raceTimeout } from 'vs/base/common/async';
import product from 'vs/platform/product/common/product';
import * as path from 'vs/base/common/path';
import * as semver from 'semver-umd';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -214,6 +213,8 @@ export class Main {
throw new Error('Invalid vsix');
}
const semver = await import('semver-umd');
const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
const newer = installedExtensions.find(local => areSameExtensions(extensionIdentifier, local.identifier) && semver.gt(local.manifest.version, manifest.version));

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as cp from 'child_process';
import { spawn } from 'child_process';
import { generateUuid } from 'vs/base/common/uuid';
import { isWindows } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
@@ -30,7 +30,7 @@ function getUnixShellEnvironment(logService: ILogService): Promise<typeof proces
logService.trace('getUnixShellEnvironment#env', env);
logService.trace('getUnixShellEnvironment#spawn', command);
const child = cp.spawn(process.env.SHELL!, ['-ilc', command], {
const child = spawn(process.env.SHELL!, ['-ilc', command], {
detached: true,
stdio: ['ignore', 'pipe', process.stderr],
env
@@ -82,8 +82,7 @@ function getUnixShellEnvironment(logService: ILogService): Promise<typeof proces
return promise.catch(() => ({}));
}
let _shellEnv: Promise<typeof process.env>;
let shellEnvPromise: Promise<typeof process.env> | undefined = undefined;
/**
* We need to get the environment from a user's shell.
@@ -91,21 +90,21 @@ let _shellEnv: Promise<typeof process.env>;
* from within a shell.
*/
export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise<typeof process.env> {
if (_shellEnv === undefined) {
if (!shellEnvPromise) {
if (environmentService.args['disable-user-env-probe']) {
logService.trace('getShellEnvironment: disable-user-env-probe set, skipping');
_shellEnv = Promise.resolve({});
shellEnvPromise = Promise.resolve({});
} else if (isWindows) {
logService.trace('getShellEnvironment: running on Windows, skipping');
_shellEnv = Promise.resolve({});
shellEnvPromise = Promise.resolve({});
} else if (process.env['VSCODE_CLI'] === '1' && process.env['VSCODE_FORCE_USER_ENV'] !== '1') {
logService.trace('getShellEnvironment: running on CLI, skipping');
_shellEnv = Promise.resolve({});
shellEnvPromise = Promise.resolve({});
} else {
logService.trace('getShellEnvironment: running on Unix');
_shellEnv = getUnixShellEnvironment(logService);
shellEnvPromise = getUnixShellEnvironment(logService);
}
}
return _shellEnv;
return shellEnvPromise;
}

View File

@@ -28,9 +28,8 @@ suite('Windows Native Helpers', () => {
});
test('vscode-windows-ca-certs', async () => {
const windowsCerts = await new Promise<any>((resolve, reject) => {
require(['vscode-windows-ca-certs'], resolve, reject);
});
// @ts-ignore Windows only
const windowsCerts = await import('vscode-windows-ca-certs');
assert.ok(windowsCerts, 'Unable to load vscode-windows-ca-certs dependency.');
});

View File

@@ -72,7 +72,7 @@ interface InMemoryClipboardMetadata {
* Every time we read from the cipboard, if the text matches our last written text,
* we can fetch the previous metadata.
*/
class InMemoryClipboardMetadataManager {
export class InMemoryClipboardMetadataManager {
public static readonly INSTANCE = new InMemoryClipboardMetadataManager();
private _lastState: InMemoryClipboardMetadata | null;

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