Merge branch 'master' into ben/folder-id

This commit is contained in:
Benjamin Pasero
2021-01-22 11:27:03 +01:00
committed by GitHub
83 changed files with 4210 additions and 3511 deletions
+1
View File
@@ -976,6 +976,7 @@
"vscode-dts-interface-naming": "warn",
"vscode-dts-cancellation": "warn",
"vscode-dts-use-thenable": "warn",
"vscode-dts-region-comments": "warn",
"vscode-dts-provider-naming": [
"warn",
{
+4 -1
View File
@@ -11,10 +11,13 @@
"dependencies": {
"@actions/core": "^1.2.6",
"@octokit/rest": "^18.0.12",
"@slack/web-api": "^6.0.0"
"@slack/web-api": "^6.0.0",
"azure-storage": "^2.10.3",
"stream-buffers": "^3.0.2"
},
"devDependencies": {
"@types/node": "^14.14.22",
"@types/stream-buffers": "^3.0.3",
"typescript": "^4.1.3"
}
}
+60 -28
View File
@@ -6,23 +6,25 @@
import * as core from '@actions/core';
import { Octokit, RestEndpointMethodTypes } from '@octokit/rest';
import { WebClient } from '@slack/web-api';
import * as storage from 'azure-storage';
import { WritableStreamBuffer } from 'stream-buffers';
(async () => {
const actionUrl = core.getInput('workflow_run_url');
const url = actionUrl || 'https://api.github.com/repos/microsoft/vscode/actions/runs/500731641';
console.log(url);
const parts = url.split('/');
const owner = parts[parts.length - 5];
const repo = parts[parts.length - 4];
const runId = parseInt(parts[parts.length - 1], 10);
if (actionUrl) {
await handleNotification(owner, repo, runId);
} else {
const results = await buildComplete(owner, repo, runId);
for (const message of [...results.logMessages, ...results.messages]) {
console.log(message);
}
}
const actionUrl = core.getInput('workflow_run_url');
const url = actionUrl || 'https://api.github.com/repos/microsoft/vscode/actions/runs/501214268';
console.log(url);
const parts = url.split('/');
const owner = parts[parts.length - 5];
const repo = parts[parts.length - 4];
const runId = parseInt(parts[parts.length - 1], 10);
if (actionUrl) {
await handleNotification(owner, repo, runId);
} else {
const results = await buildComplete(owner, repo, runId);
for (const message of [...results.logMessages, ...results.messages]) {
console.log(message);
}
}
})()
.then(null, console.error);
@@ -116,8 +118,10 @@ async function buildComplete(owner: string, repo: string, runId: number) {
const vscode = repo === 'vscode';
const name = vscode ? `VS Code ${buildResult.name} Build` : buildResult.name;
// TBD: `Requester: ${vstsToSlackUser(build.requester, build.degraded)}${pingBenForSmokeTests && releaseBuild && build.result === 'partiallySucceeded' ? ' | Ping: @bpasero' : ''}`
const accounts = await readAccounts();
const githubAccountMap = githubToAccounts(accounts);
const messages = transitionedBuilds.map(build => `${name}
Result: ${build.data.conclusion} | Branch: ${build.data.head_branch} | Authors: ${githubToSlackUsers(build.authors, build.degraded).sort().join(', ') || `None (rebuild)`}
Result: ${build.data.conclusion} | Branch: ${build.data.head_branch} | Authors: ${githubToSlackUsers(githubAccountMap, build.authors, build.degraded).sort().join(', ') || `None (rebuild)`}
Build: ${build.buildHtmlUrl}
Changes: ${build.changesHtmlUrl}`);
return { logMessages, messages };
@@ -141,23 +145,51 @@ async function compareCommits(octokit: Octokit, owner: string, repo: string, bas
return octokit.repos.compareCommits({ owner, repo, base, head });
}
function githubToSlackUsers(githubUsers: string[], at?: boolean) {
function githubToSlackUsers(githubToAccounts: Record<string, Accounts>, githubUsers: string[], at?: boolean) {
return githubUsers.map(g => githubToAccounts[g] ? `${at ? '@' : ''}${githubToAccounts[g].slack}` : g);
}
const accounts = [
{
github: 'tbd',
slack: 'tbd'
interface Accounts {
github: string;
slack: string;
vsts: string;
}
function githubToAccounts(accounts: Accounts[]) {
return accounts.reduce((m, e) => {
m[e.github] = e;
return m;
}, <Record<string, Accounts>>{});
}
async function readAccounts() {
const connectionString = process.env.BUILD_CHAT_STORAGE_CONNECTION_STRING;
if (!connectionString) {
console.error('Connection string missing.');
return [];
}
];
const buf = await readFile(connectionString, 'config', '/', 'accounts.json');
return JSON.parse(buf.toString()) as Accounts[];
}
type Accounts = (typeof accounts)[0];
const githubToAccounts = accounts.reduce((m, e) => {
m[e.github] = e;
return m;
}, <Record<string, Accounts>>{});
async function readFile(connectionString: string, share: string, directory: string, filename: string) {
return new Promise<Buffer>((resolve, reject) => {
const stream = new WritableStreamBuffer()
const fileService = storage.createFileService(connectionString);
fileService.getFileToStream(share, directory, filename, stream, err => {
if (err) {
reject(err);
} else {
const contents = stream.getContents();
if (contents) {
resolve(contents);
} else {
reject(new Error('No content'));
}
}
});
});
}
interface AllChannels {
channels: {
+434 -2
View File
@@ -155,11 +155,50 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
"@types/stream-buffers@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/stream-buffers/-/stream-buffers-3.0.3.tgz#34e565bf64e3e4bdeee23fd4aa58d4636014a02b"
integrity sha512-NeFeX7YfFZDYsCfbuaOmFQ0OjSmHreKBpp7MQ4alWQBHeh2USLsj7qyMyn9t82kjqIX516CR/5SRHnARduRtbQ==
dependencies:
"@types/node" "*"
ajv@^6.12.3:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.8.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
@@ -167,18 +206,64 @@ axios@^0.21.1:
dependencies:
follow-redirects "^1.10.0"
azure-storage@^2.10.3:
version "2.10.3"
resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.3.tgz#c5966bf929d87587d78f6847040ea9a4b1d4a50a"
integrity sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==
dependencies:
browserify-mime "~1.2.9"
extend "^3.0.2"
json-edm-parser "0.1.2"
md5.js "1.3.4"
readable-stream "~2.0.0"
request "^2.86.0"
underscore "~1.8.3"
uuid "^3.0.0"
validator "~9.4.1"
xml2js "0.2.8"
xmlbuilder "^9.0.7"
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
before-after-hook@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
combined-stream@^1.0.6:
browserify-mime@~1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/browserify-mime/-/browserify-mime-1.2.9.tgz#aeb1af28de6c0d7a6a2ce40adb68ff18422af31f"
integrity sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -189,6 +274,14 @@ deprecation@^2.0.0, deprecation@^2.3.1:
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
eventemitter3@^3.1.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
@@ -199,11 +292,41 @@ eventemitter3@^4.0.4:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
extend@^3.0.2, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
follow-redirects@^1.10.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7"
integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
@@ -213,6 +336,58 @@ form-data@^2.5.0:
combined-stream "^1.0.6"
mime-types "^2.1.12"
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.3:
version "5.1.5"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
dependencies:
ajv "^6.12.3"
har-schema "^2.0.0"
hash-base@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
dependencies:
inherits "^2.0.4"
readable-stream "^3.6.0"
safe-buffer "^5.2.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
@@ -223,12 +398,77 @@ is-stream@^1.1.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
json-edm-parser@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/json-edm-parser/-/json-edm-parser-0.1.2.tgz#1e60b0fef1bc0af67bc0d146dfdde5486cd615b4"
integrity sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=
dependencies:
jsonparse "~1.2.0"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsonparse@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.2.0.tgz#5c0c5685107160e72fe7489bddea0b44c2bc67bd"
integrity sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.2.3"
verror "1.10.0"
md5.js@1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0=
dependencies:
hash-base "^3.0.0"
inherits "^2.0.1"
mime-db@1.45.0:
version "1.45.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
mime-types@^2.1.12:
mime-types@^2.1.12, mime-types@~2.1.19:
version "2.1.28"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
@@ -240,6 +480,11 @@ node-fetch@^2.6.1:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -275,22 +520,209 @@ p-timeout@^3.2.0:
dependencies:
p-finally "^1.0.0"
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
integrity sha1-j5A0HmilPMySh4jaz80Rs265t44=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
request@^2.86.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
retry@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sax@0.5.x:
version "0.5.8"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
stream-buffers@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.2.tgz#5249005a8d5c2d00b3a32e6e0a6ea209dc4f3521"
integrity sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
typescript@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
underscore@~1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=
universal-user-agent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^3.0.0, uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
validator@~9.4.1:
version "9.4.1"
resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663"
integrity sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==
verror@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xml2js@0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2"
integrity sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=
dependencies:
sax "0.5.x"
xmlbuilder@^9.0.7:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
+1
View File
@@ -33,3 +33,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
BUILD_CHAT_STORAGE_CONNECTION_STRING: ${{ secrets.BUILD_CHAT_STORAGE_CONNECTION_STRING }}
@@ -0,0 +1,14 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const retry_1 = require("./retry");
const { installBrowsersWithProgressBar } = require('playwright/lib/install/installer');
const playwrightPath = path.dirname(require.resolve('playwright'));
async function install() {
await retry_1.retry(() => installBrowsersWithProgressBar(playwrightPath));
}
install();
@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import { retry } from './retry';
const { installBrowsersWithProgressBar } = require('playwright/lib/install/installer');
const playwrightPath = path.dirname(require.resolve('playwright'));
async function install() {
await retry(() => installBrowsersWithProgressBar(playwrightPath));
}
install();
@@ -0,0 +1,35 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiEventNaming {
constructor() {
this.meta = {
messages: {
comment: 'region comments should start with the GH issue link, e.g #region https://github.com/microsoft/vscode/issues/<number>',
}
};
}
create(context) {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node) => {
for (let comment of sourceCode.getAllComments()) {
if (comment.type !== 'Line') {
continue;
}
if (!comment.value.match(/^\s*#region /)) {
continue;
}
if (!comment.value.match(/https:\/\/github.com\/microsoft\/vscode\/issues\/\d+/i)) {
context.report({
node: comment,
messageId: 'comment',
});
}
}
}
};
}
};
@@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
export = new class ApiEventNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
comment: 'region comments should start with the GH issue link, e.g #region https://github.com/microsoft/vscode/issues/<number>',
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node: any) => {
for (let comment of sourceCode.getAllComments()) {
if (comment.type !== 'Line') {
continue;
}
if (!comment.value.match(/^\s*#region /)) {
continue;
}
if (!comment.value.match(/https:\/\/github.com\/microsoft\/vscode\/issues\/\d+/i)) {
context.report({
node: <any>comment,
messageId: 'comment',
});
}
}
}
};
}
};
+3 -2
View File
@@ -165,7 +165,8 @@ function minifyTask(src, sourceMapBaseUrl) {
const esbuild = require('esbuild');
const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return cb => {
const minifyCSS = require('gulp-cssnano');
const cssnano = require('cssnano');
const postcss = require('gulp-postcss');
const sourcemaps = require('gulp-sourcemaps');
const jsFilter = filter('**/*.js', { restore: true });
const cssFilter = filter('**/*.css', { restore: true });
@@ -185,7 +186,7 @@ function minifyTask(src, sourceMapBaseUrl) {
f.sourceMap = JSON.parse(sourceMapFile.text);
cb(undefined, f);
}, cb);
}), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => {
}), jsFilter.restore, cssFilter, postcss([cssnano({ preset: 'default' })]), cssFilter.restore, sourcemaps.mapSources((sourcePath) => {
if (sourcePath === 'bootstrap-fork.js') {
return 'bootstrap-fork.orig.js';
}
+3 -2
View File
@@ -236,7 +236,8 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) =>
const sourceMappingURL = sourceMapBaseUrl ? ((f: any) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return cb => {
const minifyCSS = require('gulp-cssnano') as typeof import('gulp-cssnano');
const cssnano = require('cssnano') as typeof import('cssnano');
const postcss = require('gulp-postcss') as typeof import('gulp-postcss');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const jsFilter = filter('**/*.js', { restore: true });
@@ -267,7 +268,7 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) =>
}),
jsFilter.restore,
cssFilter,
minifyCSS({ reduceIdents: false }),
postcss([cssnano({ preset: 'default' })]),
cssFilter.restore,
(<any>sourcemaps).mapSources((sourcePath: string) => {
if (sourcePath === 'bootstrap-fork.js') {
-12
View File
@@ -1,12 +0,0 @@
declare module "gulp-cssnano" {
function f(opts:{reduceIdents:boolean;}): NodeJS.ReadWriteStream;
/**
* This is required as per:
* https://github.com/microsoft/TypeScript/issues/5073
*/
namespace f {}
export = f;
}
+167 -202
View File
@@ -354,13 +354,15 @@
dependencies:
eslint-visitor-keys "^1.1.0"
ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=
ajv@^6.12.3:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
applicationinsights@1.0.8:
version "1.0.8"
@@ -390,42 +392,37 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ=
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
aws-sign2@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8=
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.2.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=
aws4@^1.8.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
azure-storage@^2.1.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.6.0.tgz#84747ee54a4bd194bb960f89f3eff89d67acf1cf"
integrity sha1-hHR+5UpL0ZS7lg+J8+/4nWes8c8=
version "2.10.3"
resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.3.tgz#c5966bf929d87587d78f6847040ea9a4b1d4a50a"
integrity sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==
dependencies:
browserify-mime "~1.2.9"
extend "~1.2.1"
extend "^3.0.2"
json-edm-parser "0.1.2"
md5.js "1.3.4"
readable-stream "~2.0.0"
request "~2.81.0"
request "^2.86.0"
underscore "~1.8.3"
uuid "^3.0.0"
validator "~3.35.0"
xml2js "0.2.7"
xmlbuilder "0.4.3"
validator "~9.4.1"
xml2js "0.2.8"
xmlbuilder "^9.0.7"
balanced-match@^1.0.0:
version "1.0.0"
@@ -454,13 +451,6 @@ boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
boom@2.x.x:
version "2.10.1"
resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=
dependencies:
hoek "2.x.x"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -514,15 +504,10 @@ cheerio@^1.0.0-rc.1:
lodash "^4.15.0"
parse5 "^3.0.1"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
@@ -551,13 +536,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=
dependencies:
boom "2.x.x"
css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
@@ -724,21 +702,26 @@ estraverse@^4.1.0, estraverse@^4.1.1:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
extend@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-1.2.1.tgz#a0f5fd6cfc83a5fe49ef698d60ec8a624dd4576c"
integrity sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=
extend@^3.0.2, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extend@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=
extsprintf@1.3.0, extsprintf@^1.2.0:
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
@@ -756,13 +739,13 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@~2.1.1:
version "2.1.4"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
combined-stream "^1.0.6"
mime-types "^2.1.12"
fs.realpath@^1.0.0:
@@ -801,41 +784,27 @@ glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio=
har-validator@~5.1.3:
version "5.1.5"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
dependencies:
ajv "^4.9.1"
har-schema "^1.0.5"
ajv "^6.12.3"
har-schema "^2.0.0"
hash-base@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
version "3.1.0"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=
dependencies:
boom "2.x.x"
cryptiles "2.x.x"
hoek "2.x.x"
sntp "1.x.x"
hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=
inherits "^2.0.4"
readable-stream "^3.6.0"
safe-buffer "^5.2.0"
htmlparser2@^3.9.1:
version "3.10.0"
@@ -849,12 +818,12 @@ htmlparser2@^3.9.1:
inherits "^2.0.1"
readable-stream "^3.0.6"
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^0.2.0"
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
@@ -871,12 +840,12 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2:
inherits@2, inherits@^2.0.1, inherits@^2.0.4, inherits@~2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1:
inherits@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
@@ -932,18 +901,16 @@ json-edm-parser@0.1.2:
dependencies:
jsonparse "~1.2.0"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=
dependencies:
jsonify "~0.0.0"
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@@ -954,11 +921,6 @@ jsonc-parser@^2.3.0:
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee"
integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA==
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
jsonparse@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.2.0.tgz#5c0c5685107160e72fe7489bddea0b44c2bc67bd"
@@ -1027,17 +989,17 @@ mdurl@^1.0.1:
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
mime-db@~1.30.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=
mime-db@1.45.0:
version "1.45.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
mime-types@^2.1.12, mime-types@~2.1.7:
version "2.1.17"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=
mime-types@^2.1.12, mime-types@~2.1.19:
version "2.1.28"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
dependencies:
mime-db "~1.30.0"
mime-db "1.45.0"
mime@^1.3.4:
version "1.4.1"
@@ -1098,10 +1060,10 @@ nth-check@~1.0.1:
dependencies:
boolbase "~1.0.0"
oauth-sign@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
once@^1.3.0:
version "1.4.0"
@@ -1152,10 +1114,10 @@ pend@~1.2.0:
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
plist@^3.0.1:
version "3.0.1"
@@ -1176,20 +1138,25 @@ process-nextick-args@~1.0.6:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
q@^1.0.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
read@^1.0.7:
version "1.0.7"
@@ -1207,6 +1174,15 @@ readable-stream@^3.0.6:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
@@ -1219,38 +1195,36 @@ readable-stream@~2.0.0:
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
request@~2.81.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=
request@^2.86.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
form-data "~2.3.2"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
performance-now "^0.2.0"
qs "~6.4.0"
safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.0.0"
uuid "^3.3.2"
safe-buffer@^5.0.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-buffer@~5.1.0:
version "5.1.2"
@@ -1262,10 +1236,10 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sax@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.2.tgz#735ffaa39a1cff8ffb9598f0223abdb03a9fb2ea"
integrity sha1-c1/6o5oc/4/7lZjwIjq9sDqfsuo=
sax@0.5.x:
version "0.5.8"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
semaphore@^1.0.5:
version "1.1.0"
@@ -1289,13 +1263,6 @@ semver@^7.3.2:
dependencies:
lru-cache "^6.0.0"
sntp@1.x.x:
version "1.0.9"
resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=
dependencies:
hoek "2.x.x"
source-map@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -1333,11 +1300,6 @@ string_decoder@~0.10.x:
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
stringstream@~0.0.4:
version "0.0.6"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
tmp@0.0.29:
version "0.0.29"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0"
@@ -1345,12 +1307,13 @@ tmp@0.0.29:
dependencies:
os-tmpdir "~1.0.1"
tough-cookie@~2.3.0:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE=
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
punycode "^1.4.1"
psl "^1.1.28"
punycode "^2.1.1"
tslib@^1.8.1:
version "1.9.3"
@@ -1419,6 +1382,13 @@ universal-user-agent@^6.0.0:
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
url-join@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78"
@@ -1429,20 +1399,20 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==
uuid@^3.0.0, uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^8.3.0:
version "8.3.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
validator@~3.35.0:
version "3.35.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-3.35.0.tgz#3f07249402c1fc8fc093c32c6e43d72a79cca1dc"
integrity sha1-PwcklALB/I/Ak8MsbkPXKnnModw=
validator@~9.4.1:
version "9.4.1"
resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663"
integrity sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==
verror@1.10.0:
version "1.10.0"
@@ -1491,17 +1461,12 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xml2js@0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.7.tgz#1838518bb01741cae0878bab4915e494c32306af"
integrity sha1-GDhRi7AXQcrgh4urSRXklMMjBq8=
xml2js@0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2"
integrity sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=
dependencies:
sax "0.5.2"
xmlbuilder@0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-0.4.3.tgz#c4614ba74e0ad196e609c9272cd9e1ddb28a8a58"
integrity sha1-xGFLp04K0ZbmCcknLNnh3bKKilg=
sax "0.5.x"
xmlbuilder@^9.0.7:
version "9.0.7"
+5
View File
@@ -71,6 +71,11 @@
"category": "Git",
"icon": "$(compare-changes)"
},
{
"command": "git.openAllChanges",
"title": "%command.openAllChanges%",
"category": "Git"
},
{
"command": "git.openFile",
"title": "%command.openFile%",
+1
View File
@@ -9,6 +9,7 @@
"command.close": "Close Repository",
"command.refresh": "Refresh",
"command.openChange": "Open Changes",
"command.openAllChanges": "Open All Changes",
"command.openFile": "Open File",
"command.openHEADFile": "Open File (HEAD)",
"command.stage": "Stage Changes",
+14
View File
@@ -372,6 +372,20 @@ export class CommandCenter {
await resource.open();
}
@command('git.openAllChanges', { repository: true })
async openChanges(repository: Repository): Promise<void> {
[
...repository.workingTreeGroup.resourceStates,
...repository.untrackedGroup.resourceStates,
].forEach(resource => {
commands.executeCommand(
'vscode.open',
resource.resourceUri,
{ preview: false, }
);
});
}
async cloneRepository(url?: string, parentPath?: string, options: { recursive?: boolean } = {}): Promise<void> {
if (!url || typeof url !== 'string') {
url = await pickRemoteSource(this.model, {
-5
View File
@@ -1,8 +1,3 @@
# Simple Browser files
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
a $a + b = c$ b
a $\pm\sqrt{a^2 + b^2}$ b
+2 -1
View File
@@ -46,7 +46,7 @@ export function activate(context: vscode.ExtensionContext) {
manager.show(url.toString(), showOptions);
}));
context.subscriptions.push(vscode.window.registerExternalUriOpener(openerId, ['http', 'https'], {
context.subscriptions.push(vscode.window.registerExternalUriOpener(openerId, {
canOpenExternalUri(uri: vscode.Uri) {
const originalUri = new URL(uri.toString());
if (enabledHosts.has(originalUri.hostname)) {
@@ -63,6 +63,7 @@ export function activate(context: vscode.ExtensionContext) {
});
}
}, {
schemes: ['http', 'https'],
label: localize('openTitle', "Open in simple browser"),
}));
}
+28 -2
View File
@@ -19,7 +19,8 @@
"onCommand:vscode-testresolver.newWindow",
"onCommand:vscode-testresolver.newWindowWithError",
"onCommand:vscode-testresolver.showLog",
"onCommand:vscode-testresolver.openTunnel"
"onCommand:vscode-testresolver.openTunnel",
"onCommand:vscode-testresolver.startRemoteServer"
],
"main": "./out/extension",
"devDependencies": {
@@ -55,12 +56,27 @@
"command": "vscode-testresolver.killServerAndTriggerHandledError"
},
{
"title": "Open Tunnel 100",
"title": "Open Tunnel...",
"category": "Remote-TestResolver",
"command": "vscode-testresolver.openTunnel"
},
{
"title": "Open Remote Server...",
"category": "Remote-TestResolver",
"command": "vscode-testresolver.startRemoteServer"
}
],
"menus": {
"commandPalette": [
{
"command": "vscode-testresolver.openTunnel",
"when": "remoteName == test"
},
{
"command": "vscode-testresolver.startRemoteServer",
"when": "remoteName == test"
}
],
"statusBar/windowIndicator": [
{
"command": "vscode-testresolver.newWindow",
@@ -76,6 +92,16 @@
"command": "vscode-testresolver.newWindow",
"when": "remoteName == test",
"group": "1_remote_testresolver_open@1"
},
{
"command": "vscode-testresolver.openTunnel",
"when": "remoteName == test",
"group": "1_remote_testresolver_open@4"
},
{
"command": "vscode-testresolver.startRemoteServer",
"when": "remoteName == test",
"group": "1_remote_testresolver_open@5"
}
]
},
@@ -9,6 +9,7 @@ import * as path from 'path';
import * as fs from 'fs';
import * as os from 'os';
import * as net from 'net';
import * as http from 'http';
import { downloadAndUnzipVSCodeServer } from './download';
import { terminateProcess } from './util/processes';
@@ -216,7 +217,7 @@ export function activate(context: vscode.ExtensionContext) {
},
tunnelFactory,
tunnelFeatures: { elevation: true, public: false },
showCandidatePort: async (_host, port) => port === 100
showCandidatePort
});
context.subscriptions.push(authorityResolverDisposable);
@@ -245,14 +246,35 @@ export function activate(context: vscode.ExtensionContext) {
outputChannel.show();
}
}));
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.openTunnel', () => {
vscode.workspace.openTunnel({
remoteAddress: {
host: 'localhost',
port: 100
},
localAddressPort: 100
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.openTunnel', async () => {
const result = await vscode.window.showInputBox({
prompt: 'Enter the remote port for the tunnel',
value: '5000',
validateInput: input => /^[\d]+$/.test(input) ? undefined : 'Not a valid number'
});
if (result) {
const port = Number.parseInt(result);
vscode.workspace.openTunnel({
remoteAddress: {
host: 'localhost',
port: port
},
localAddressPort: port + 1
});
}
}));
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.startRemoteServer', async () => {
const result = await vscode.window.showInputBox({
prompt: 'Enter the port for the remote server',
value: '5000',
validateInput: input => /^[\d]+$/.test(input) ? undefined : 'Not a valid number'
});
if (result) {
runHTTPTestServer(Number.parseInt(result));
}
}));
vscode.commands.executeCommand('setContext', 'forwardedPortsViewEnabled', true);
}
@@ -316,13 +338,19 @@ function getConfiguration<T>(id: string): T | undefined {
return vscode.workspace.getConfiguration('testresolver').get<T>(id);
}
function tunnelFactory(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunnel> | undefined {
let remotePort = tunnelOptions.remoteAddress.port;
if (remotePort === 100) {
return createTunnelService();
}
return undefined;
const remoteServers: number[] = [];
async function showCandidatePort(_host: string, port: number, _detail: string): Promise<boolean> {
return remoteServers.includes(port) || port === 100;
}
async function tunnelFactory(tunnelOptions: vscode.TunnelOptions, tunnelCreationOptions: vscode.TunnelCreationOptions): Promise<vscode.Tunnel> {
outputChannel.appendLine(`Tunnel factory request: Remote ${tunnelOptions.remoteAddress.port} -> local ${tunnelOptions.localAddressPort}`);
if (tunnelCreationOptions.elevationRequired) {
await vscode.window.showInformationMessage('This is a fake elevation message. A real resolver would show a native elevation prompt.', { modal: true }, 'Ok');
}
return createTunnelService();
function newTunnel(localAddress: { host: string, port: number }) {
const onDidDispose: vscode.EventEmitter<void> = new vscode.EventEmitter();
@@ -344,14 +372,32 @@ function tunnelFactory(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunn
function createTunnelService(): Promise<vscode.Tunnel> {
return new Promise<vscode.Tunnel>((res, _rej) => {
const proxyServer = net.createServer(proxySocket => {
outputChannel.appendLine(`Connection accepted`);
const remoteSocket = net.createConnection({ host: tunnelOptions.remoteAddress.host, port: tunnelOptions.remoteAddress.port });
remoteSocket.pipe(proxySocket);
proxySocket.pipe(remoteSocket);
});
proxyServer.listen(tunnelOptions.localAddressPort === undefined ? 0 : tunnelOptions.localAddressPort, () => {
let localPort = 0;
if (tunnelOptions.localAddressPort) {
// When the tunnelOptions include a localAddressPort, we should use that.
// However, the test resolver all runs on one machine, so if the localAddressPort is the same as the remote port,
// then we must use a different port number.
localPort = tunnelOptions.localAddressPort;
} else {
localPort = tunnelOptions.remoteAddress.port;
}
if (localPort === tunnelOptions.remoteAddress.port) {
localPort += 1;
}
// The test resolver can't actually handle privileged ports, it only pretends to.
if (localPort < 1024 && process.platform !== 'win32') {
localPort = 0;
}
proxyServer.listen(localPort, () => {
const localPort = (<net.AddressInfo>proxyServer.address()).port;
console.log(`New test resolver tunnel service: Remote ${tunnelOptions.remoteAddress.port} -> local ${localPort}`);
outputChannel.appendLine(`New test resolver tunnel service: Remote ${tunnelOptions.remoteAddress.port} -> local ${localPort}`);
const tunnel = newTunnel({ host: 'localhost', port: localPort });
tunnel.onDidDispose(() => proxyServer.close());
res(tunnel);
@@ -359,3 +405,24 @@ function tunnelFactory(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunn
});
}
}
function runHTTPTestServer(port: number): vscode.Disposable {
const server = http.createServer((_req, res) => {
res.writeHead(200);
res.end(`Hello, World from test server running on port ${port}!`);
});
remoteServers.push(port);
server.listen(port);
const message = `Opened HTTP server on http://localhost:${port}`;
console.log(message);
outputChannel.appendLine(message);
return {
dispose: () => {
server.close();
const index = remoteServers.indexOf(port);
if (index !== -1) {
remoteServers.splice(index, 1);
}
}
};
}
+14 -8
View File
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.53.0",
"distro": "9743d4c538f650da5636ce1b2994c719dfa8e953",
"distro": "65cbf43543d86e78b90fb749d535c3d3ed9dd3a5",
"author": {
"name": "Microsoft Corporation"
},
@@ -47,7 +47,7 @@
"watch-web": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js watch-web",
"eslint": "node build/eslint",
"electron-rebuild": "electron-rebuild --arch=arm64 --force --version=11.2.0",
"playwright-install": "node node_modules/playwright/install.js",
"playwright-install": "node build/azure-pipelines/common/installPlaywright.js",
"compile-build": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile-build",
"compile-extensions-build": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js compile-extensions-build",
"minify-vscode": "node --max_old_space_size=4095 ./node_modules/gulp/bin/gulp.js minify-vscode",
@@ -98,8 +98,10 @@
"@types/chokidar": "2.1.3",
"@types/cookie": "^0.3.3",
"@types/copy-webpack-plugin": "^6.0.3",
"@types/cssnano": "^4.0.0",
"@types/debug": "4.1.5",
"@types/graceful-fs": "4.1.2",
"@types/gulp-postcss": "^8.0.0",
"@types/http-proxy-agent": "^2.0.1",
"@types/keytar": "^4.4.0",
"@types/minimist": "^1.2.1",
@@ -123,6 +125,7 @@
"copy-webpack-plugin": "^6.0.3",
"cson-parser": "^1.3.3",
"css-loader": "^3.2.0",
"cssnano": "^4.1.10",
"debounce": "^1.0.0",
"deemon": "^1.4.0",
"electron": "11.2.0",
@@ -133,15 +136,13 @@
"fancy-log": "^1.3.3",
"fast-plist": "0.1.2",
"file-loader": "^4.2.0",
"github-releases": "^0.4.1",
"glob": "^5.0.13",
"gulp": "^4.0.0",
"gulp-atom-electron": "^1.22.0",
"gulp-azure-storage": "^0.11.1",
"gulp-bom": "^1.0.0",
"gulp-bom": "^3.0.0",
"gulp-buffer": "0.0.2",
"gulp-concat": "^2.6.1",
"gulp-cssnano": "^2.1.3",
"gulp-eslint": "^5.0.0",
"gulp-filter": "^5.1.0",
"gulp-flatmap": "^1.0.2",
@@ -149,11 +150,12 @@
"gulp-gzip": "^1.4.2",
"gulp-json-editor": "^2.5.0",
"gulp-plumber": "^1.2.0",
"gulp-postcss": "^9.0.0",
"gulp-remote-retry-src": "^0.6.0",
"gulp-rename": "^1.2.0",
"gulp-replace": "^0.5.4",
"gulp-shell": "^0.6.5",
"gulp-sourcemaps": "^1.11.0",
"gulp-sourcemaps": "^3.0.0",
"gulp-tsb": "4.0.5",
"gulp-untar": "^0.0.7",
"gulp-vinyl-zip": "^2.1.2",
@@ -189,8 +191,8 @@
"source-map": "0.6.1",
"source-map-support": "^0.3.2",
"style-loader": "^1.0.0",
"tsec": "0.1.1",
"ts-loader": "^6.2.1",
"tsec": "0.1.1",
"typescript": "4.2.0-dev.20201207",
"typescript-formatter": "7.1.0",
"underscore": "^1.8.2",
@@ -218,5 +220,9 @@
"windows-foreground-love": "0.2.0",
"windows-mutex": "0.3.0",
"windows-process-tree": "0.2.4"
},
"resolutions": {
"elliptic": "^6.5.3",
"nwmatcher": "^1.4.4"
}
}
}
+13 -16
View File
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions, IObjectTreeSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTree';
import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper, ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
@@ -20,7 +20,6 @@ import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/
import { IThemable } from 'vs/base/common/styler';
import { isFilterResult, getVisibleState } from 'vs/base/browser/ui/tree/indexTreeModel';
import { treeItemLoadingIcon } from 'vs/base/browser/ui/tree/treeIcons';
import { IObjectTreeSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -280,7 +279,7 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
}
export interface IAsyncDataTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { }
export interface IAsyncDataTreeUpdateChildrenOptions<T, TFilterData> extends IObjectTreeSetChildrenOptions<T, TFilterData> { }
export interface IAsyncDataTreeUpdateChildrenOptions<T> extends IObjectTreeSetChildrenOptions<T> { }
export interface IAsyncDataTreeOptions<T, TFilterData = void> extends IAsyncDataTreeOptionsUpdate, Pick<IAbstractTreeOptions<T, TFilterData>, Exclude<keyof IAbstractTreeOptions<T, TFilterData>, 'collapseByDefault'>> {
readonly collapseByDefault?: { (e: T): boolean; };
@@ -501,11 +500,11 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
}
async updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, options?: IAsyncDataTreeUpdateChildrenOptions<T | TInput, TFilterData>): Promise<void> {
async updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, options?: IAsyncDataTreeUpdateChildrenOptions<T>): Promise<void> {
await this._updateChildren(element, recursive, rerender, undefined, options);
}
private async _updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T | TInput, TFilterData>): Promise<void> {
private async _updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T>): Promise<void> {
if (typeof this.root.element === 'undefined') {
throw new TreeError(this.user, 'Tree input not set');
}
@@ -706,7 +705,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return node;
}
private async refreshAndRenderNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T | TInput, TFilterData>): Promise<void> {
private async refreshAndRenderNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T>): Promise<void> {
await this.refreshNode(node, recursive, viewStateContext);
this.render(node, viewStateContext, options);
}
@@ -923,20 +922,18 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return childrenToRefresh;
}
protected render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T, TFilterData>): void {
protected render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T>): void {
const children = node.children.map(node => this.asTreeElement(node, viewStateContext));
const diffIdentity = options?.diffIdentityProvider;
const treeOptions = options ? {
diffIdentityProvider: diffIdentity ? {
const objectTreeOptions: IObjectTreeSetChildrenOptions<IAsyncDataTreeNode<TInput, T>> | undefined = options && {
...options,
diffIdentityProvider: options!.diffIdentityProvider && {
getId(node: IAsyncDataTreeNode<TInput, T>): { toString(): string; } {
return diffIdentity.getId(node.element as T);
return options!.diffIdentityProvider!.getId(node.element as T);
}
} : undefined,
diffDept: options.diffDepth
} : undefined;
}
};
this.tree.setChildren(node === this.root ? null : node, children, treeOptions);
this.tree.setChildren(node === this.root ? null : node, children, objectTreeOptions);
if (node !== this.root) {
this.tree.setCollapsible(node, node.hasChildren);
@@ -6,8 +6,8 @@
import { Iterable } from 'vs/base/common/iterator';
import { Event } from 'vs/base/common/event';
import { ITreeModel, ITreeNode, ITreeElement, ICollapseStateChangeEvent, ITreeModelSpliceEvent, TreeError, TreeFilterResult, TreeVisibility, WeakMapper } from 'vs/base/browser/ui/tree/tree';
import { IObjectTreeModelOptions, ObjectTreeModel, IObjectTreeModel, IObjectTreeSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IIndexedSpliceOptions, IList } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IObjectTreeModelOptions, ObjectTreeModel, IObjectTreeModel, IObjectTreeModelSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IIndexTreeModelSpliceOptions, IList } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
// Exported only for test reasons, do not use directly
@@ -144,7 +144,7 @@ export class CompressedObjectTreeModel<T extends NonNullable<any>, TFilterData e
setChildren(
element: T | null,
children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(),
options: IObjectTreeSetChildrenOptions<T, TFilterData>,
options: IObjectTreeModelSetChildrenOptions<T, TFilterData>,
): void {
// Diffs must be deem, since the compression can affect nested elements.
// @see https://github.com/microsoft/vscode/pull/114237#issuecomment-759425034
@@ -206,7 +206,7 @@ export class CompressedObjectTreeModel<T extends NonNullable<any>, TFilterData e
private _setChildren(
node: ICompressedTreeNode<T> | null,
children: Iterable<ITreeElement<ICompressedTreeNode<T>>>,
options: IIndexedSpliceOptions<ICompressedTreeNode<T>, TFilterData>,
options: IIndexTreeModelSpliceOptions<ICompressedTreeNode<T>, TFilterData>,
): void {
const insertedElements = new Set<T | null>();
const onDidCreateNode = (node: ITreeNode<ICompressedTreeNode<T>, TFilterData>) => {
@@ -451,7 +451,7 @@ export class CompressibleObjectTreeModel<T extends NonNullable<any>, TFilterData
setChildren(
element: T | null,
children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(),
options: IObjectTreeSetChildrenOptions<T, TFilterData> = {},
options: IObjectTreeModelSetChildrenOptions<T, TFilterData> = {},
): void {
this.model.setChildren(element, children, options);
}
@@ -43,7 +43,7 @@ export interface IIndexTreeModelOptions<T, TFilterData> {
readonly autoExpandSingleChildren?: boolean;
}
export interface IIndexedSpliceOptions<T, TFilterData> {
export interface IIndexTreeModelSpliceOptions<T, TFilterData> {
/**
* If set, child updates will recurse the given number of levels even if
* items in the splice operation are unchanged. `Infinity` is a valid value.
@@ -140,7 +140,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
location: number[],
deleteCount: number,
toInsert: Iterable<ITreeElement<T>> = Iterable.empty(),
options: IIndexedSpliceOptions<T, TFilterData> = {},
options: IIndexTreeModelSpliceOptions<T, TFilterData> = {},
): void {
if (location.length === 0) {
throw new TreeError(this.user, 'Invalid tree location');
@@ -158,7 +158,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
location: number[],
deleteCount: number,
toInsertIterable: Iterable<ITreeElement<T>> = Iterable.empty(),
options: IIndexedSpliceOptions<T, TFilterData>,
options: IIndexTreeModelSpliceOptions<T, TFilterData>,
recurseLevels = options.diffDepth ?? 0,
) {
const { parentNode } = this.getParentNodeWithListIndex(location);
@@ -221,7 +221,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
location: number[],
deleteCount: number,
toInsert: Iterable<ITreeElement<T>> = Iterable.empty(),
{ onDidCreateNode, onDidDeleteNode }: IIndexedSpliceOptions<T, TFilterData>,
{ onDidCreateNode, onDidDeleteNode }: IIndexTreeModelSpliceOptions<T, TFilterData>,
) {
const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);
const treeListElementsToInsert: ITreeNode<T, TFilterData>[] = [];
+23 -4
View File
@@ -6,8 +6,8 @@
import { Iterable } from 'vs/base/common/iterator';
import { AbstractTree, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
import { ObjectTreeModel, IObjectTreeModel, IObjectTreeSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list';
import { ObjectTreeModel, IObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IListVirtualDelegate, IKeyboardNavigationLabelProvider, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { Event } from 'vs/base/common/event';
import { CompressibleObjectTreeModel, ElementMapper, ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { memoize } from 'vs/base/common/decorators';
@@ -17,6 +17,25 @@ export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTree
readonly sorter?: ITreeSorter<T>;
}
export interface IObjectTreeSetChildrenOptions<T> {
/**
* If set, child updates will recurse the given number of levels even if
* items in the splice operation are unchanged. `Infinity` is a valid value.
*/
readonly diffDepth?: number;
/**
* Identity provider used to optimize splice() calls in the IndexTree. If
* this is not present, optimized splicing is not enabled.
*
* Warning: if this is present, calls to `setChildren()` will not replace
* or update nodes if their identity is the same, even if the elements are
* different. For this, you should call `rerender()`.
*/
readonly diffIdentityProvider?: IIdentityProvider<T>;
}
export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
protected model!: IObjectTreeModel<T, TFilterData>;
@@ -33,7 +52,7 @@ export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends
super(user, container, delegate, renderers, options as IObjectTreeOptions<T | null, TFilterData>);
}
setChildren(element: T | null, children: Iterable<ITreeElement<T>> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions<T, TFilterData>): void {
setChildren(element: T | null, children: Iterable<ITreeElement<T>> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions<T>): void {
this.model.setChildren(element, children, options);
}
@@ -189,7 +208,7 @@ export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = vo
super(user, container, delegate, compressibleRenderers, asObjectTreeOptions<T, TFilterData>(compressedTreeNodeProvider, options));
}
setChildren(element: T | null, children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(), options: IObjectTreeSetChildrenOptions<T, TFilterData> = {}): void {
setChildren(element: T | null, children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions<T>): void {
this.model.setChildren(element, children, options);
}
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Iterable } from 'vs/base/common/iterator';
import { IndexTreeModel, IIndexTreeModelOptions, IList, IIndexedSpliceOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IndexTreeModel, IIndexTreeModelOptions, IList, IIndexTreeModelSpliceOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
import { Event } from 'vs/base/common/event';
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent, TreeError } from 'vs/base/browser/ui/tree/tree';
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
@@ -13,12 +13,12 @@ import { mergeSort } from 'vs/base/common/arrays';
export type ITreeNodeCallback<T, TFilterData> = (node: ITreeNode<T, TFilterData>) => void;
export interface IObjectTreeModel<T extends NonNullable<any>, TFilterData extends NonNullable<any> = void> extends ITreeModel<T | null, TFilterData, T | null> {
setChildren(element: T | null, children: Iterable<ITreeElement<T>> | undefined, options?: IObjectTreeSetChildrenOptions<T, TFilterData>): void;
setChildren(element: T | null, children: Iterable<ITreeElement<T>> | undefined, options?: IObjectTreeModelSetChildrenOptions<T, TFilterData>): void;
resort(element?: T | null, recursive?: boolean): void;
updateElementHeight(element: T, height: number): void;
}
export interface IObjectTreeSetChildrenOptions<T, TFilterData> extends IIndexedSpliceOptions<T, TFilterData> {
export interface IObjectTreeModelSetChildrenOptions<T, TFilterData> extends IIndexTreeModelSpliceOptions<T, TFilterData> {
}
export interface IObjectTreeModelOptions<T, TFilterData> extends IIndexTreeModelOptions<T, TFilterData> {
@@ -66,7 +66,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
setChildren(
element: T | null,
children: Iterable<ITreeElement<T>> = Iterable.empty(),
options: IObjectTreeSetChildrenOptions<T, TFilterData> = {},
options: IObjectTreeModelSetChildrenOptions<T, TFilterData> = {},
): void {
const location = this.getElementLocation(element);
this._setChildren(location, this.preserveCollapseState(children), options);
@@ -75,7 +75,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
private _setChildren(
location: number[],
children: Iterable<ITreeElement<T>> = Iterable.empty(),
options: IObjectTreeSetChildrenOptions<T, TFilterData>,
options: IObjectTreeModelSetChildrenOptions<T, TFilterData>,
): void {
const insertedElements = new Set<T | null>();
const insertedElementIds = new Set<string>();
@@ -38,7 +38,7 @@ export class Client extends MessagePortClient implements IDisposable {
export async function connect(window: BrowserWindow): Promise<MessagePortMain> {
// Assert healthy window to talk to
if (window.webContents.isDestroyed()) {
if (window.isDestroyed() || window.webContents.isDestroyed()) {
throw new Error('ipc.mp#connect: Cannot talk to window because it is closed or destroyed');
}
@@ -8,7 +8,7 @@ import { compress, ICompressedTreeElement, ICompressedTreeNode, decompress, Comp
import { Iterable } from 'vs/base/common/iterator';
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
import { IList } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IObjectTreeSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IObjectTreeModelSetChildrenOptions } from 'vs/base/browser/ui/tree/objectTreeModel';
interface IResolvedCompressedTreeElement<T> extends ICompressedTreeElement<T> {
readonly element: T;
@@ -309,7 +309,7 @@ suite('CompressedObjectTree', function () {
* Calls that test function twice, once with an empty options and
* once with `diffIdentityProvider`.
*/
function withSmartSplice(fn: (options: IObjectTreeSetChildrenOptions<number, any>) => void) {
function withSmartSplice(fn: (options: IObjectTreeModelSetChildrenOptions<number, any>) => void) {
fn({});
fn({ diffIdentityProvider: { getId: n => String(n) } });
}
@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { ITreeNode, ITreeFilter, TreeVisibility, ITreeElement } from 'vs/base/browser/ui/tree/tree';
import { IndexTreeModel, IIndexTreeNode, IList, IIndexedSpliceOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IndexTreeModel, IIndexTreeNode, IList, IIndexTreeModelSpliceOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
function toList<T>(arr: T[]): IList<T> {
return {
@@ -31,7 +31,7 @@ const diffIdentityProvider = { getId: (n: number) => String(n) };
* Calls that test function twice, once with an empty options and
* once with `diffIdentityProvider`.
*/
function withSmartSplice(fn: (options: IIndexedSpliceOptions<number, any>) => void) {
function withSmartSplice(fn: (options: IIndexTreeModelSpliceOptions<number, any>) => void) {
fn({});
fn({ diffIdentityProvider });
}
+87 -87
View File
@@ -10,25 +10,25 @@ suite('Arrays', () => {
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
let idx = arrays.findFirstInSorted(array, e => e >= 0);
assert.equal(array[idx], 1);
assert.strictEqual(array[idx], 1);
idx = arrays.findFirstInSorted(array, e => e > 1);
assert.equal(array[idx], 4);
assert.strictEqual(array[idx], 4);
idx = arrays.findFirstInSorted(array, e => e >= 8);
assert.equal(array[idx], 55);
assert.strictEqual(array[idx], 55);
idx = arrays.findFirstInSorted(array, e => e >= 61);
assert.equal(array[idx], 61);
assert.strictEqual(array[idx], 61);
idx = arrays.findFirstInSorted(array, e => e >= 69);
assert.equal(array[idx], 69);
assert.strictEqual(array[idx], 69);
idx = arrays.findFirstInSorted(array, e => e >= 70);
assert.equal(idx, array.length);
assert.strictEqual(idx, array.length);
idx = arrays.findFirstInSorted([], e => e >= 0);
assert.equal(array[idx], 1);
assert.strictEqual(array[idx], 1);
});
test('quickSelect', () => {
@@ -36,10 +36,10 @@ suite('Arrays', () => {
function assertMedian(expexted: number, data: number[], nth: number = Math.floor(data.length / 2)) {
const compare = (a: number, b: number) => a - b;
let actual1 = arrays.quickSelect(nth, data, compare);
assert.equal(actual1, expexted);
assert.strictEqual(actual1, expexted);
let actual2 = data.slice().sort(compare)[nth];
assert.equal(actual2, expexted);
assert.strictEqual(actual2, expexted);
}
assertMedian(5, [9, 1, 0, 2, 3, 4, 6, 8, 7, 10, 5]);
@@ -72,18 +72,18 @@ suite('Arrays', () => {
test('mergeSort', () => {
let data = arrays.mergeSort([6, 5, 3, 1, 8, 7, 2, 4], (a, b) => a - b);
assert.deepEqual(data, [1, 2, 3, 4, 5, 6, 7, 8]);
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6, 7, 8]);
});
test('mergeSort, sorted array', function () {
let data = arrays.mergeSort([1, 2, 3, 4, 5, 6], (a, b) => a - b);
assert.deepEqual(data, [1, 2, 3, 4, 5, 6]);
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6]);
});
test('mergeSort, is stable', function () {
let numbers = arrays.mergeSort([33, 22, 11, 4, 99, 1], (a, b) => 0);
assert.deepEqual(numbers, [33, 22, 11, 4, 99, 1]);
assert.deepStrictEqual(numbers, [33, 22, 11, 4, 99, 1]);
});
test('mergeSort, many random numbers', function () {
@@ -129,40 +129,40 @@ suite('Arrays', () => {
}
let d = arrays.sortedDiff([1, 2, 4], [], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 3, toInsert: [] }
]);
d = arrays.sortedDiff([], [1, 2, 4], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 0, toInsert: [1, 2, 4] }
]);
d = arrays.sortedDiff([1, 2, 4], [1, 2, 4], compare);
assert.deepEqual(d, []);
assert.deepStrictEqual(d, []);
d = arrays.sortedDiff([1, 2, 4], [2, 3, 4, 5], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 1, toInsert: [] },
{ start: 2, deleteCount: 0, toInsert: [3] },
{ start: 3, deleteCount: 0, toInsert: [5] },
]);
d = arrays.sortedDiff([2, 3, 4, 5], [1, 2, 4], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 0, toInsert: [1] },
{ start: 1, deleteCount: 1, toInsert: [] },
{ start: 3, deleteCount: 1, toInsert: [] },
]);
d = arrays.sortedDiff([1, 3, 5, 7], [5, 9, 11], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 2, toInsert: [] },
{ start: 3, deleteCount: 1, toInsert: [9, 11] }
]);
d = arrays.sortedDiff([1, 3, 7], [5, 9, 11], compare);
assert.deepEqual(d, [
assert.deepStrictEqual(d, [
{ start: 0, deleteCount: 3, toInsert: [5, 9, 11] }
]);
});
@@ -173,32 +173,32 @@ suite('Arrays', () => {
}
let d = arrays.delta([1, 2, 4], [], compare);
assert.deepEqual(d.removed, [1, 2, 4]);
assert.deepEqual(d.added, []);
assert.deepStrictEqual(d.removed, [1, 2, 4]);
assert.deepStrictEqual(d.added, []);
d = arrays.delta([], [1, 2, 4], compare);
assert.deepEqual(d.removed, []);
assert.deepEqual(d.added, [1, 2, 4]);
assert.deepStrictEqual(d.removed, []);
assert.deepStrictEqual(d.added, [1, 2, 4]);
d = arrays.delta([1, 2, 4], [1, 2, 4], compare);
assert.deepEqual(d.removed, []);
assert.deepEqual(d.added, []);
assert.deepStrictEqual(d.removed, []);
assert.deepStrictEqual(d.added, []);
d = arrays.delta([1, 2, 4], [2, 3, 4, 5], compare);
assert.deepEqual(d.removed, [1]);
assert.deepEqual(d.added, [3, 5]);
assert.deepStrictEqual(d.removed, [1]);
assert.deepStrictEqual(d.added, [3, 5]);
d = arrays.delta([2, 3, 4, 5], [1, 2, 4], compare);
assert.deepEqual(d.removed, [3, 5]);
assert.deepEqual(d.added, [1]);
assert.deepStrictEqual(d.removed, [3, 5]);
assert.deepStrictEqual(d.added, [1]);
d = arrays.delta([1, 3, 5, 7], [5, 9, 11], compare);
assert.deepEqual(d.removed, [1, 3, 7]);
assert.deepEqual(d.added, [9, 11]);
assert.deepStrictEqual(d.removed, [1, 3, 7]);
assert.deepStrictEqual(d.added, [9, 11]);
d = arrays.delta([1, 3, 7], [5, 9, 11], compare);
assert.deepEqual(d.removed, [1, 3, 7]);
assert.deepEqual(d.added, [5, 9, 11]);
assert.deepStrictEqual(d.removed, [1, 3, 7]);
assert.deepStrictEqual(d.added, [5, 9, 11]);
});
test('binarySearch', () => {
@@ -207,13 +207,13 @@ suite('Arrays', () => {
}
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
assert.equal(arrays.binarySearch(array, 1, compare), 0);
assert.equal(arrays.binarySearch(array, 5, compare), 2);
assert.strictEqual(arrays.binarySearch(array, 1, compare), 0);
assert.strictEqual(arrays.binarySearch(array, 5, compare), 2);
// insertion point
assert.equal(arrays.binarySearch(array, 0, compare), ~0);
assert.equal(arrays.binarySearch(array, 6, compare), ~3);
assert.equal(arrays.binarySearch(array, 70, compare), ~10);
assert.strictEqual(arrays.binarySearch(array, 0, compare), ~0);
assert.strictEqual(arrays.binarySearch(array, 6, compare), ~3);
assert.strictEqual(arrays.binarySearch(array, 70, compare), ~10);
});
@@ -222,11 +222,11 @@ suite('Arrays', () => {
return a;
}
assert.deepEqual(arrays.distinct(['32', '4', '5'], compare), ['32', '4', '5']);
assert.deepEqual(arrays.distinct(['32', '4', '5', '4'], compare), ['32', '4', '5']);
assert.deepEqual(arrays.distinct(['32', 'constructor', '5', '1'], compare), ['32', 'constructor', '5', '1']);
assert.deepEqual(arrays.distinct(['32', 'constructor', 'proto', 'proto', 'constructor'], compare), ['32', 'constructor', 'proto']);
assert.deepEqual(arrays.distinct(['32', '4', '5', '32', '4', '5', '32', '4', '5', '5'], compare), ['32', '4', '5']);
assert.deepStrictEqual(arrays.distinct(['32', '4', '5'], compare), ['32', '4', '5']);
assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '4'], compare), ['32', '4', '5']);
assert.deepStrictEqual(arrays.distinct(['32', 'constructor', '5', '1'], compare), ['32', 'constructor', '5', '1']);
assert.deepStrictEqual(arrays.distinct(['32', 'constructor', 'proto', 'proto', 'constructor'], compare), ['32', 'constructor', 'proto']);
assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '32', '4', '5', '32', '4', '5', '5'], compare), ['32', '4', '5']);
});
test('top', () => {
@@ -236,13 +236,13 @@ suite('Arrays', () => {
return a - b;
};
assert.deepEqual(arrays.top([], cmp, 1), []);
assert.deepEqual(arrays.top([1], cmp, 0), []);
assert.deepEqual(arrays.top([1, 2], cmp, 1), [1]);
assert.deepEqual(arrays.top([2, 1], cmp, 1), [1]);
assert.deepEqual(arrays.top([1, 3, 2], cmp, 2), [1, 2]);
assert.deepEqual(arrays.top([3, 2, 1], cmp, 3), [1, 2, 3]);
assert.deepEqual(arrays.top([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3), [1, 2, 3]);
assert.deepStrictEqual(arrays.top([], cmp, 1), []);
assert.deepStrictEqual(arrays.top([1], cmp, 0), []);
assert.deepStrictEqual(arrays.top([1, 2], cmp, 1), [1]);
assert.deepStrictEqual(arrays.top([2, 1], cmp, 1), [1]);
assert.deepStrictEqual(arrays.top([1, 3, 2], cmp, 2), [1, 2]);
assert.deepStrictEqual(arrays.top([3, 2, 1], cmp, 3), [1, 2, 3]);
assert.deepStrictEqual(arrays.top([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3), [1, 2, 3]);
});
test('topAsync', async () => {
@@ -259,56 +259,56 @@ suite('Arrays', () => {
async function testTopAsync(cmp: any, m: number) {
{
const result = await arrays.topAsync([], cmp, 1, m);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
}
{
const result = await arrays.topAsync([1], cmp, 0, m);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
}
{
const result = await arrays.topAsync([1, 2], cmp, 1, m);
assert.deepEqual(result, [1]);
assert.deepStrictEqual(result, [1]);
}
{
const result = await arrays.topAsync([2, 1], cmp, 1, m);
assert.deepEqual(result, [1]);
assert.deepStrictEqual(result, [1]);
}
{
const result = await arrays.topAsync([1, 3, 2], cmp, 2, m);
assert.deepEqual(result, [1, 2]);
assert.deepStrictEqual(result, [1, 2]);
}
{
const result = await arrays.topAsync([3, 2, 1], cmp, 3, m);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
}
{
const result = await arrays.topAsync([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3, m);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
}
}
test('coalesce', () => {
let a: Array<number | null> = arrays.coalesce([null, 1, null, 2, 3]);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
assert.strictEqual(a[2], 3);
arrays.coalesce([null, 1, null, undefined, undefined, 2, 3]);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
assert.strictEqual(a[2], 3);
let b: number[] = [];
b[10] = 1;
b[20] = 2;
b[30] = 3;
b = arrays.coalesce(b);
assert.equal(b.length, 3);
assert.equal(b[0], 1);
assert.equal(b[1], 2);
assert.equal(b[2], 3);
assert.strictEqual(b.length, 3);
assert.strictEqual(b[0], 1);
assert.strictEqual(b[1], 2);
assert.strictEqual(b[2], 3);
let sparse: number[] = [];
sparse[0] = 1;
@@ -317,36 +317,36 @@ suite('Arrays', () => {
sparse[1000] = 1;
sparse[1001] = 1;
assert.equal(sparse.length, 1002);
assert.strictEqual(sparse.length, 1002);
sparse = arrays.coalesce(sparse);
assert.equal(sparse.length, 5);
assert.strictEqual(sparse.length, 5);
});
test('coalesce - inplace', function () {
let a: Array<number | null> = [null, 1, null, 2, 3];
arrays.coalesceInPlace(a);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
assert.strictEqual(a[2], 3);
a = [null, 1, null, undefined!, undefined!, 2, 3];
arrays.coalesceInPlace(a);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
assert.equal(a[2], 3);
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
assert.strictEqual(a[2], 3);
let b: number[] = [];
b[10] = 1;
b[20] = 2;
b[30] = 3;
arrays.coalesceInPlace(b);
assert.equal(b.length, 3);
assert.equal(b[0], 1);
assert.equal(b[1], 2);
assert.equal(b[2], 3);
assert.strictEqual(b.length, 3);
assert.strictEqual(b[0], 1);
assert.strictEqual(b[1], 2);
assert.strictEqual(b[2], 3);
let sparse: number[] = [];
sparse[0] = 1;
@@ -355,18 +355,18 @@ suite('Arrays', () => {
sparse[1000] = 1;
sparse[1001] = 1;
assert.equal(sparse.length, 1002);
assert.strictEqual(sparse.length, 1002);
arrays.coalesceInPlace(sparse);
assert.equal(sparse.length, 5);
assert.strictEqual(sparse.length, 5);
});
test('insert, remove', function () {
const array: string[] = [];
const remove = arrays.insert(array, 'foo');
assert.equal(array[0], 'foo');
assert.strictEqual(array[0], 'foo');
remove();
assert.equal(array.length, 0);
assert.strictEqual(array.length, 0);
});
});
+87 -87
View File
@@ -18,7 +18,7 @@ suite('Async', () => {
return new Promise(resolve => { /*never*/ });
});
let result = promise.then(_ => assert.ok(false), err => {
assert.equal(canceled, 1);
assert.strictEqual(canceled, 1);
assert.ok(isPromiseCanceledError(err));
});
promise.cancel();
@@ -33,7 +33,7 @@ suite('Async', () => {
return Promise.resolve(1234);
});
let result = promise.then(_ => assert.ok(false), err => {
assert.equal(canceled, 1);
assert.strictEqual(canceled, 1);
assert.ok(isPromiseCanceledError(err));
});
promise.cancel();
@@ -60,7 +60,7 @@ suite('Async', () => {
cancellablePromise.cancel();
order.push('afterCancel');
return promise.then(() => assert.deepEqual(order, ['in callback', 'afterCreate', 'cancelled', 'afterCancel', 'finally']));
return promise.then(() => assert.deepStrictEqual(order, ['in callback', 'afterCreate', 'cancelled', 'afterCancel', 'finally']));
});
// Cancelling an async cancelable promise is just the same as a sync cancellable promise.
@@ -82,7 +82,7 @@ suite('Async', () => {
cancellablePromise.cancel();
order.push('afterCancel');
return promise.then(() => assert.deepEqual(order, ['in callback', 'afterCreate', 'cancelled', 'afterCancel', 'finally']));
return promise.then(() => assert.deepStrictEqual(order, ['in callback', 'afterCreate', 'cancelled', 'afterCancel', 'finally']));
});
test('cancelablePromise - get inner result', async function () {
@@ -91,7 +91,7 @@ suite('Async', () => {
});
let result = await promise;
assert.equal(result, 1234);
assert.strictEqual(result, 1234);
});
test('Throttler - non async', function () {
@@ -103,12 +103,12 @@ suite('Async', () => {
let throttler = new async.Throttler();
return Promise.all([
throttler.queue(factory).then((result) => { assert.equal(result, 1); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); })
]).then(() => assert.equal(count, 2));
throttler.queue(factory).then((result) => { assert.strictEqual(result, 1); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); })
]).then(() => assert.strictEqual(count, 2));
});
test('Throttler', () => {
@@ -118,18 +118,18 @@ suite('Async', () => {
let throttler = new async.Throttler();
return Promise.all([
throttler.queue(factory).then((result) => { assert.equal(result, 1); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); }),
throttler.queue(factory).then((result) => { assert.equal(result, 2); })
throttler.queue(factory).then((result) => { assert.strictEqual(result, 1); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 2); })
]).then(() => {
return Promise.all([
throttler.queue(factory).then((result) => { assert.equal(result, 3); }),
throttler.queue(factory).then((result) => { assert.equal(result, 4); }),
throttler.queue(factory).then((result) => { assert.equal(result, 4); }),
throttler.queue(factory).then((result) => { assert.equal(result, 4); }),
throttler.queue(factory).then((result) => { assert.equal(result, 4); })
throttler.queue(factory).then((result) => { assert.strictEqual(result, 3); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 4); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 4); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 4); }),
throttler.queue(factory).then((result) => { assert.strictEqual(result, 4); })
]);
});
});
@@ -143,9 +143,9 @@ suite('Async', () => {
let promises: Promise<any>[] = [];
promises.push(throttler.queue(factoryFactory(1)).then((n) => { assert.equal(n, 1); }));
promises.push(throttler.queue(factoryFactory(2)).then((n) => { assert.equal(n, 3); }));
promises.push(throttler.queue(factoryFactory(3)).then((n) => { assert.equal(n, 3); }));
promises.push(throttler.queue(factoryFactory(1)).then((n) => { assert.strictEqual(n, 1); }));
promises.push(throttler.queue(factoryFactory(2)).then((n) => { assert.strictEqual(n, 3); }));
promises.push(throttler.queue(factoryFactory(3)).then((n) => { assert.strictEqual(n, 3); }));
return Promise.all(promises);
});
@@ -161,13 +161,13 @@ suite('Async', () => {
assert(!delayer.isTriggered());
promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()); }));
promises.push(delayer.trigger(factory).then((result) => { assert.strictEqual(result, 1); assert(!delayer.isTriggered()); }));
assert(delayer.isTriggered());
promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()); }));
promises.push(delayer.trigger(factory).then((result) => { assert.strictEqual(result, 1); assert(!delayer.isTriggered()); }));
assert(delayer.isTriggered());
promises.push(delayer.trigger(factory).then((result) => { assert.equal(result, 1); assert(!delayer.isTriggered()); }));
promises.push(delayer.trigger(factory).then((result) => { assert.strictEqual(result, 1); assert(!delayer.isTriggered()); }));
assert(delayer.isTriggered());
return Promise.all(promises).then(() => {
@@ -237,7 +237,7 @@ suite('Async', () => {
assert(!delayer.isTriggered());
const p = delayer.trigger(factory).then((result) => {
assert.equal(result, 1);
assert.strictEqual(result, 1);
assert(!delayer.isTriggered());
promises.push(delayer.trigger(factory).then(undefined, () => { assert(true, 'yes, it was cancelled'); }));
@@ -253,10 +253,10 @@ suite('Async', () => {
assert(!delayer.isTriggered());
promises.push(delayer.trigger(factory).then(() => { assert.equal(result, 1); assert(!delayer.isTriggered()); }));
promises.push(delayer.trigger(factory).then(() => { assert.strictEqual(result, 1); assert(!delayer.isTriggered()); }));
assert(delayer.isTriggered());
promises.push(delayer.trigger(factory).then(() => { assert.equal(result, 1); assert(!delayer.isTriggered()); }));
promises.push(delayer.trigger(factory).then(() => { assert.strictEqual(result, 1); assert(!delayer.isTriggered()); }));
assert(delayer.isTriggered());
const p = Promise.all(promises).then(() => {
@@ -286,9 +286,9 @@ suite('Async', () => {
assert(!delayer.isTriggered());
promises.push(delayer.trigger(factoryFactory(1)).then((n) => { assert.equal(n, 3); }));
promises.push(delayer.trigger(factoryFactory(2)).then((n) => { assert.equal(n, 3); }));
promises.push(delayer.trigger(factoryFactory(3)).then((n) => { assert.equal(n, 3); }));
promises.push(delayer.trigger(factoryFactory(1)).then((n) => { assert.strictEqual(n, 3); }));
promises.push(delayer.trigger(factoryFactory(2)).then((n) => { assert.strictEqual(n, 3); }));
promises.push(delayer.trigger(factoryFactory(3)).then((n) => { assert.strictEqual(n, 3); }));
const p = Promise.all(promises).then(() => {
assert(!delayer.isTriggered());
@@ -311,12 +311,12 @@ suite('Async', () => {
factoryFactory(4),
factoryFactory(5),
]).then((result) => {
assert.equal(5, result.length);
assert.equal(1, result[0]);
assert.equal(2, result[1]);
assert.equal(3, result[2]);
assert.equal(4, result[3]);
assert.equal(5, result[4]);
assert.strictEqual(5, result.length);
assert.strictEqual(1, result[0]);
assert.strictEqual(2, result[1]);
assert.strictEqual(3, result[2]);
assert.strictEqual(4, result[3]);
assert.strictEqual(5, result[4]);
});
});
@@ -331,7 +331,7 @@ suite('Async', () => {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n))));
return Promise.all(promises).then((res) => {
assert.equal(10, res.length);
assert.strictEqual(10, res.length);
limiter = new async.Limiter(100);
@@ -339,7 +339,7 @@ suite('Async', () => {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n))));
return Promise.all(promises).then((res) => {
assert.equal(10, res.length);
assert.strictEqual(10, res.length);
});
});
});
@@ -352,7 +352,7 @@ suite('Async', () => {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n))));
return Promise.all(promises).then((res) => {
assert.equal(10, res.length);
assert.strictEqual(10, res.length);
limiter = new async.Limiter(100);
@@ -360,7 +360,7 @@ suite('Async', () => {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n))));
return Promise.all(promises).then((res) => {
assert.equal(10, res.length);
assert.strictEqual(10, res.length);
});
});
});
@@ -379,8 +379,8 @@ suite('Async', () => {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(n => promises.push(limiter.queue(factoryFactory(n))));
return Promise.all(promises).then((res) => {
assert.equal(10, res.length);
assert.deepEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], res);
assert.strictEqual(10, res.length);
assert.deepStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], res);
});
});
@@ -393,15 +393,15 @@ suite('Async', () => {
let asyncPromise = false;
let f2 = () => async.timeout(10).then(() => asyncPromise = true);
assert.equal(queue.size, 0);
assert.strictEqual(queue.size, 0);
queue.queue(f1);
assert.equal(queue.size, 1);
assert.strictEqual(queue.size, 1);
const p = queue.queue(f2);
assert.equal(queue.size, 2);
assert.strictEqual(queue.size, 2);
return p.then(() => {
assert.equal(queue.size, 0);
assert.strictEqual(queue.size, 0);
assert.ok(syncPromise);
assert.ok(asyncPromise);
});
@@ -423,11 +423,11 @@ suite('Async', () => {
queue.queue(f3);
queue.queue(f4);
return queue.queue(f5).then(() => {
assert.equal(res[0], 1);
assert.equal(res[1], 2);
assert.equal(res[2], 3);
assert.equal(res[3], 4);
assert.equal(res[4], 5);
assert.strictEqual(res[0], 1);
assert.strictEqual(res[1], 2);
assert.strictEqual(res[2], 3);
assert.strictEqual(res[3], 4);
assert.strictEqual(res[4], 5);
});
});
@@ -448,11 +448,11 @@ suite('Async', () => {
queue.queue(f3).then(undefined, () => error = true);
queue.queue(f4);
return queue.queue(f5).then(() => {
assert.equal(res[0], 1);
assert.equal(res[1], 2);
assert.strictEqual(res[0], 1);
assert.strictEqual(res[1], 2);
assert.ok(error);
assert.equal(res[2], 4);
assert.equal(res[3], 5);
assert.strictEqual(res[2], 4);
assert.strictEqual(res[3], 5);
});
});
@@ -472,11 +472,11 @@ suite('Async', () => {
return queue.queue(f3).then(() => {
return queue.queue(f4).then(() => {
return queue.queue(f5).then(() => {
assert.equal(res[0], 1);
assert.equal(res[1], 2);
assert.equal(res[2], 3);
assert.equal(res[3], 4);
assert.equal(res[4], 5);
assert.strictEqual(res[0], 1);
assert.strictEqual(res[1], 2);
assert.strictEqual(res[2], 3);
assert.strictEqual(res[3], 4);
assert.strictEqual(res[4], 5);
});
});
});
@@ -521,7 +521,7 @@ suite('Async', () => {
assert.ok(r1Queue);
assert.ok(r2Queue);
assert.equal(r1Queue, queue.queueFor(URI.file('/some/path'))); // same queue returned
assert.strictEqual(r1Queue, queue.queueFor(URI.file('/some/path'))); // same queue returned
let syncPromiseFactory = () => Promise.resolve(undefined);
@@ -545,7 +545,7 @@ suite('Async', () => {
return Promise.resolve(true);
}, 10, 3);
assert.equal(res, true);
assert.strictEqual(res, true);
});
test('retry - error case', async () => {
@@ -555,7 +555,7 @@ suite('Async', () => {
return Promise.reject(expectedError);
}, 10, 3);
} catch (error) {
assert.equal(error, error);
assert.strictEqual(error, error);
}
});
@@ -673,7 +673,7 @@ suite('Async', () => {
await p1;
assert.ok(!triggered);
assert.equal(timedout, true);
assert.strictEqual(timedout, true);
// promise wins
timedout = false;
@@ -684,32 +684,32 @@ suite('Async', () => {
await p2;
assert.ok(triggered);
assert.equal(timedout, false);
assert.strictEqual(timedout, false);
});
test('SequencerByKey', async () => {
const s = new async.SequencerByKey<string>();
const r1 = await s.queue('key1', () => Promise.resolve('hello'));
assert.equal(r1, 'hello');
assert.strictEqual(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');
assert.strictEqual(err.message, 'failed');
});
// Still works after a queued promise is rejected
const r3 = await s.queue('key2', () => Promise.resolve('hello'));
assert.equal(r3, 'hello');
assert.strictEqual(r3, 'hello');
});
test('IntervalCounter', async () => {
const counter = new async.IntervalCounter(10);
assert.equal(counter.increment(), 1);
assert.equal(counter.increment(), 2);
assert.equal(counter.increment(), 3);
assert.strictEqual(counter.increment(), 1);
assert.strictEqual(counter.increment(), 2);
assert.strictEqual(counter.increment(), 3);
const now = Date.now();
await async.timeout(20);
@@ -717,9 +717,9 @@ suite('Async', () => {
return; // Firefox in Playwright seems to have a flaky timeout implementation (https://github.com/microsoft/vscode/issues/114028)
}
assert.equal(counter.increment(), 1);
assert.equal(counter.increment(), 2);
assert.equal(counter.increment(), 3);
assert.strictEqual(counter.increment(), 1);
assert.strictEqual(counter.increment(), 2);
assert.strictEqual(counter.increment(), 3);
});
test('firstParallel - simple', async () => {
@@ -728,19 +728,19 @@ suite('Async', () => {
Promise.resolve(2),
Promise.resolve(3),
], v => v === 2);
assert.equal(a, 2);
assert.strictEqual(a, 2);
});
test('firstParallel - uses null default', async () => {
assert.equal(await async.firstParallel([Promise.resolve(1)], v => v === 2), null);
assert.strictEqual(await async.firstParallel([Promise.resolve(1)], v => v === 2), null);
});
test('firstParallel - uses value default', async () => {
assert.equal(await async.firstParallel([Promise.resolve(1)], v => v === 2, 4), 4);
assert.strictEqual(await async.firstParallel([Promise.resolve(1)], v => v === 2, 4), 4);
});
test('firstParallel - empty', async () => {
assert.equal(await async.firstParallel([], v => v === 2, 4), 4);
assert.strictEqual(await async.firstParallel([], v => v === 2, 4), 4);
});
test('firstParallel - cancels', async () => {
@@ -757,9 +757,9 @@ suite('Async', () => {
return 2;
});
assert.equal(await async.firstParallel([p1, p2], v => v === 2, 4), 2);
assert.equal(ct1!.isCancellationRequested, true, 'should cancel a');
assert.equal(ct2!.isCancellationRequested, true, 'should cancel b');
assert.strictEqual(await async.firstParallel([p1, p2], v => v === 2, 4), 2);
assert.strictEqual(ct1!.isCancellationRequested, true, 'should cancel a');
assert.strictEqual(ct2!.isCancellationRequested, true, 'should cancel b');
});
test('firstParallel - rejection handling', async () => {
@@ -776,9 +776,9 @@ suite('Async', () => {
throw new Error('oh no');
});
assert.equal(await async.firstParallel([p1, p2], v => v === 2, 4).catch(() => 'ok'), 'ok');
assert.equal(ct1!.isCancellationRequested, true, 'should cancel a');
assert.equal(ct2!.isCancellationRequested, true, 'should cancel b');
assert.strictEqual(await async.firstParallel([p1, p2], v => v === 2, 4).catch(() => 'ok'), 'ok');
assert.strictEqual(ct1!.isCancellationRequested, true, 'should cancel a');
assert.strictEqual(ct2!.isCancellationRequested, true, 'should cancel b');
});
suite('DeferredPromise', () => {
+12 -12
View File
@@ -8,17 +8,17 @@ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cance
suite('CancellationToken', function () {
test('None', () => {
assert.equal(CancellationToken.None.isCancellationRequested, false);
assert.equal(typeof CancellationToken.None.onCancellationRequested, 'function');
assert.strictEqual(CancellationToken.None.isCancellationRequested, false);
assert.strictEqual(typeof CancellationToken.None.onCancellationRequested, 'function');
});
test('cancel before token', function (done) {
const source = new CancellationTokenSource();
assert.equal(source.token.isCancellationRequested, false);
assert.strictEqual(source.token.isCancellationRequested, false);
source.cancel();
assert.equal(source.token.isCancellationRequested, true);
assert.strictEqual(source.token.isCancellationRequested, true);
source.token.onCancellationRequested(function () {
assert.ok(true);
@@ -29,7 +29,7 @@ suite('CancellationToken', function () {
test('cancel happens only once', function () {
let source = new CancellationTokenSource();
assert.equal(source.token.isCancellationRequested, false);
assert.strictEqual(source.token.isCancellationRequested, false);
let cancelCount = 0;
function onCancel() {
@@ -41,7 +41,7 @@ suite('CancellationToken', function () {
source.cancel();
source.cancel();
assert.equal(cancelCount, 1);
assert.strictEqual(cancelCount, 1);
});
test('cancel calls all listeners', function () {
@@ -60,7 +60,7 @@ suite('CancellationToken', function () {
});
source.cancel();
assert.equal(count, 3);
assert.strictEqual(count, 3);
});
test('token stays the same', function () {
@@ -92,7 +92,7 @@ suite('CancellationToken', function () {
source.dispose();
source.cancel();
assert.equal(count, 0);
assert.strictEqual(count, 0);
});
test('dispose calls no listeners (unless told to cancel)', function () {
@@ -106,7 +106,7 @@ suite('CancellationToken', function () {
source.dispose(true);
// source.cancel();
assert.equal(count, 1);
assert.strictEqual(count, 1);
});
test('parent cancels child', function () {
@@ -119,8 +119,8 @@ suite('CancellationToken', function () {
parent.cancel();
assert.equal(count, 1);
assert.equal(child.token.isCancellationRequested, true);
assert.equal(parent.token.isCancellationRequested, true);
assert.strictEqual(count, 1);
assert.strictEqual(child.token.isCancellationRequested, true);
assert.strictEqual(parent.token.isCancellationRequested, true);
});
});
+3 -3
View File
@@ -9,7 +9,7 @@ function filterOk(filter: IFilter, word: string, wordToMatchAgainst: string, hig
let r = filter(word, wordToMatchAgainst);
assert(r, `${word} didn't match ${wordToMatchAgainst}`);
if (highlights) {
assert.deepEqual(r, highlights);
assert.deepStrictEqual(r, highlights);
}
}
@@ -233,7 +233,7 @@ suite('Filters', () => {
pos = match.end;
}
actualWord += word.substring(pos);
assert.equal(actualWord, decoratedWord);
assert.strictEqual(actualWord, decoratedWord);
}
}
@@ -442,7 +442,7 @@ suite('Filters', () => {
}
}
}
assert.equal(topIdx, expected, `${pattern} -> actual=${words[topIdx]} <> expected=${words[expected]}`);
assert.strictEqual(topIdx, expected, `${pattern} -> actual=${words[topIdx]} <> expected=${words[expected]}`);
}
test('topScore - fuzzyScore', function () {
+7 -7
View File
@@ -11,19 +11,19 @@ suite('LinkedList', function () {
function assertElements<E>(list: LinkedList<E>, ...elements: E[]) {
// check size
assert.equal(list.size, elements.length);
assert.strictEqual(list.size, elements.length);
// assert toArray
assert.deepEqual(Array.from(list), elements);
assert.deepStrictEqual(Array.from(list), elements);
// assert Symbol.iterator (1)
assert.deepEqual([...list], elements);
assert.deepStrictEqual([...list], elements);
// assert Symbol.iterator (2)
for (const item of list) {
assert.equal(item, elements.shift());
assert.strictEqual(item, elements.shift());
}
assert.equal(elements.length, 0);
assert.strictEqual(elements.length, 0);
}
test('Push/Iter', () => {
@@ -123,14 +123,14 @@ suite('LinkedList', function () {
assertElements(list, 'a', 'b');
let a = list.shift();
assert.equal(a, 'a');
assert.strictEqual(a, 'a');
assertElements(list, 'b');
list.unshift('a');
assertElements(list, 'a', 'b');
let b = list.pop();
assert.equal(b, 'b');
assert.strictEqual(b, 'b');
assertElements(list, 'a');
});
+244 -244
View File
@@ -16,8 +16,8 @@ suite('Map', () => {
map.set('bk', 'bv');
assert.deepStrictEqual([...map.keys()], ['ak', 'bk']);
assert.deepStrictEqual([...map.values()], ['av', 'bv']);
assert.equal(map.first, 'av');
assert.equal(map.last, 'bv');
assert.strictEqual(map.first, 'av');
assert.strictEqual(map.last, 'bv');
});
test('LinkedMap - Touch Old one', () => {
@@ -77,7 +77,7 @@ suite('Map', () => {
test('LinkedMap - basics', function () {
const map = new LinkedMap<string, any>();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
map.set('1', 1);
map.set('2', '2');
@@ -89,23 +89,23 @@ suite('Map', () => {
const date = Date.now();
map.set('5', date);
assert.equal(map.size, 5);
assert.equal(map.get('1'), 1);
assert.equal(map.get('2'), '2');
assert.equal(map.get('3'), true);
assert.equal(map.get('4'), obj);
assert.equal(map.get('5'), date);
assert.strictEqual(map.size, 5);
assert.strictEqual(map.get('1'), 1);
assert.strictEqual(map.get('2'), '2');
assert.strictEqual(map.get('3'), true);
assert.strictEqual(map.get('4'), obj);
assert.strictEqual(map.get('5'), date);
assert.ok(!map.get('6'));
map.delete('6');
assert.equal(map.size, 5);
assert.equal(map.delete('1'), true);
assert.equal(map.delete('2'), true);
assert.equal(map.delete('3'), true);
assert.equal(map.delete('4'), true);
assert.equal(map.delete('5'), true);
assert.strictEqual(map.size, 5);
assert.strictEqual(map.delete('1'), true);
assert.strictEqual(map.delete('2'), true);
assert.strictEqual(map.delete('3'), true);
assert.strictEqual(map.delete('4'), true);
assert.strictEqual(map.delete('5'), true);
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
assert.ok(!map.get('5'));
assert.ok(!map.get('4'));
assert.ok(!map.get('3'));
@@ -117,13 +117,13 @@ suite('Map', () => {
map.set('3', true);
assert.ok(map.has('1'));
assert.equal(map.get('1'), 1);
assert.equal(map.get('2'), '2');
assert.equal(map.get('3'), true);
assert.strictEqual(map.get('1'), 1);
assert.strictEqual(map.get('2'), '2');
assert.strictEqual(map.get('3'), true);
map.clear();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
assert.ok(!map.get('1'));
assert.ok(!map.get('2'));
assert.ok(!map.get('3'));
@@ -231,7 +231,7 @@ suite('Map', () => {
for (let i = 11; i <= 20; i++) {
cache.set(i, i);
}
assert.deepEqual(cache.size, 15);
assert.deepStrictEqual(cache.size, 15);
let values: number[] = [];
for (let i = 6; i <= 20; i++) {
values.push(cache.get(i)!);
@@ -269,14 +269,14 @@ suite('Map', () => {
let i = 0;
map.forEach((value, key) => {
if (i === 0) {
assert.equal(key, 'ak');
assert.equal(value, 'av');
assert.strictEqual(key, 'ak');
assert.strictEqual(value, 'av');
} else if (i === 1) {
assert.equal(key, 'bk');
assert.equal(value, 'bv');
assert.strictEqual(key, 'bk');
assert.strictEqual(value, 'bv');
} else if (i === 2) {
assert.equal(key, 'ck');
assert.equal(value, 'cv');
assert.strictEqual(key, 'ck');
assert.strictEqual(value, 'cv');
}
i++;
});
@@ -285,44 +285,44 @@ suite('Map', () => {
test('LinkedMap - delete Head and Tail', function () {
const map = new LinkedMap<string, number>();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
map.set('1', 1);
assert.equal(map.size, 1);
assert.strictEqual(map.size, 1);
map.delete('1');
assert.equal(map.get('1'), undefined);
assert.equal(map.size, 0);
assert.equal([...map.keys()].length, 0);
assert.strictEqual(map.get('1'), undefined);
assert.strictEqual(map.size, 0);
assert.strictEqual([...map.keys()].length, 0);
});
test('LinkedMap - delete Head', function () {
const map = new LinkedMap<string, number>();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
map.set('1', 1);
map.set('2', 2);
assert.equal(map.size, 2);
assert.strictEqual(map.size, 2);
map.delete('1');
assert.equal(map.get('2'), 2);
assert.equal(map.size, 1);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 2);
assert.strictEqual(map.get('2'), 2);
assert.strictEqual(map.size, 1);
assert.strictEqual([...map.keys()].length, 1);
assert.strictEqual([...map.keys()][0], '2');
});
test('LinkedMap - delete Tail', function () {
const map = new LinkedMap<string, number>();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
map.set('1', 1);
map.set('2', 2);
assert.equal(map.size, 2);
assert.strictEqual(map.size, 2);
map.delete('2');
assert.equal(map.get('1'), 1);
assert.equal(map.size, 1);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 1);
assert.strictEqual(map.get('1'), 1);
assert.strictEqual(map.size, 1);
assert.strictEqual([...map.keys()].length, 1);
assert.strictEqual([...map.keys()][0], '1');
});
@@ -330,100 +330,100 @@ suite('Map', () => {
const iter = new PathIterator();
iter.reset('file:///usr/bin/file.txt');
assert.equal(iter.value(), 'file:');
assert.equal(iter.hasNext(), true);
assert.equal(iter.cmp('file:'), 0);
assert.strictEqual(iter.value(), 'file:');
assert.strictEqual(iter.hasNext(), true);
assert.strictEqual(iter.cmp('file:'), 0);
assert.ok(iter.cmp('a') < 0);
assert.ok(iter.cmp('aile:') < 0);
assert.ok(iter.cmp('z') > 0);
assert.ok(iter.cmp('zile:') > 0);
iter.next();
assert.equal(iter.value(), 'usr');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'usr');
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'bin');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'bin');
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'file.txt');
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), 'file.txt');
assert.strictEqual(iter.hasNext(), false);
iter.next();
assert.equal(iter.value(), '');
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), '');
assert.strictEqual(iter.hasNext(), false);
iter.next();
assert.equal(iter.value(), '');
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), '');
assert.strictEqual(iter.hasNext(), false);
//
iter.reset('/foo/bar/');
assert.equal(iter.value(), 'foo');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'foo');
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'bar');
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), 'bar');
assert.strictEqual(iter.hasNext(), false);
});
test('URIIterator', function () {
const iter = new UriIterator(() => false);
iter.reset(URI.parse('file:///usr/bin/file.txt'));
assert.equal(iter.value(), 'file');
// assert.equal(iter.cmp('FILE'), 0);
assert.equal(iter.cmp('file'), 0);
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'file');
// assert.strictEqual(iter.cmp('FILE'), 0);
assert.strictEqual(iter.cmp('file'), 0);
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'usr');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'usr');
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'bin');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'bin');
assert.strictEqual(iter.hasNext(), true);
iter.next();
assert.equal(iter.value(), 'file.txt');
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), 'file.txt');
assert.strictEqual(iter.hasNext(), false);
iter.reset(URI.parse('file://share/usr/bin/file.txt?foo'));
// scheme
assert.equal(iter.value(), 'file');
// assert.equal(iter.cmp('FILE'), 0);
assert.equal(iter.cmp('file'), 0);
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'file');
// assert.strictEqual(iter.cmp('FILE'), 0);
assert.strictEqual(iter.cmp('file'), 0);
assert.strictEqual(iter.hasNext(), true);
iter.next();
// authority
assert.equal(iter.value(), 'share');
assert.equal(iter.cmp('SHARe'), 0);
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'share');
assert.strictEqual(iter.cmp('SHARe'), 0);
assert.strictEqual(iter.hasNext(), true);
iter.next();
// path
assert.equal(iter.value(), 'usr');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'usr');
assert.strictEqual(iter.hasNext(), true);
iter.next();
// path
assert.equal(iter.value(), 'bin');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'bin');
assert.strictEqual(iter.hasNext(), true);
iter.next();
// path
assert.equal(iter.value(), 'file.txt');
assert.equal(iter.hasNext(), true);
assert.strictEqual(iter.value(), 'file.txt');
assert.strictEqual(iter.hasNext(), true);
iter.next();
// query
assert.equal(iter.value(), 'foo');
assert.equal(iter.cmp('z') > 0, true);
assert.equal(iter.cmp('a') < 0, true);
assert.equal(iter.hasNext(), false);
assert.strictEqual(iter.value(), 'foo');
assert.strictEqual(iter.cmp('z') > 0, true);
assert.strictEqual(iter.cmp('a') < 0, true);
assert.strictEqual(iter.hasNext(), false);
});
function assertTernarySearchTree<E>(trie: TernarySearchTree<string, E>, ...elements: [string, E][]) {
@@ -432,24 +432,24 @@ suite('Map', () => {
map.set(key, value);
}
map.forEach((value, key) => {
assert.equal(trie.get(key), value);
assert.strictEqual(trie.get(key), value);
});
// forEach
let forEachCount = 0;
trie.forEach((element, key) => {
assert.equal(element, map.get(key));
assert.strictEqual(element, map.get(key));
forEachCount++;
});
assert.equal(map.size, forEachCount);
assert.strictEqual(map.size, forEachCount);
// iterator
let iterCount = 0;
for (let [key, value] of trie) {
assert.equal(value, map.get(key));
assert.strictEqual(value, map.get(key));
iterCount++;
}
assert.equal(map.size, iterCount);
assert.strictEqual(map.size, iterCount);
}
test('TernarySearchTree - set', function () {
@@ -493,13 +493,13 @@ suite('Map', () => {
trie.set('foobar', 2);
trie.set('foobaz', 3);
assert.equal(trie.findSubstr('f'), undefined);
assert.equal(trie.findSubstr('z'), undefined);
assert.equal(trie.findSubstr('foo'), 1);
assert.equal(trie.findSubstr('fooö'), 1);
assert.equal(trie.findSubstr('fooba'), 1);
assert.equal(trie.findSubstr('foobarr'), 2);
assert.equal(trie.findSubstr('foobazrr'), 3);
assert.strictEqual(trie.findSubstr('f'), undefined);
assert.strictEqual(trie.findSubstr('z'), undefined);
assert.strictEqual(trie.findSubstr('foo'), 1);
assert.strictEqual(trie.findSubstr('fooö'), 1);
assert.strictEqual(trie.findSubstr('fooba'), 1);
assert.strictEqual(trie.findSubstr('foobarr'), 2);
assert.strictEqual(trie.findSubstr('foobazrr'), 3);
});
test('TernarySearchTree - basics', function () {
@@ -509,27 +509,27 @@ suite('Map', () => {
trie.set('bar', 2);
trie.set('foobar', 3);
assert.equal(trie.get('foo'), 1);
assert.equal(trie.get('bar'), 2);
assert.equal(trie.get('foobar'), 3);
assert.equal(trie.get('foobaz'), undefined);
assert.equal(trie.get('foobarr'), undefined);
assert.strictEqual(trie.get('foo'), 1);
assert.strictEqual(trie.get('bar'), 2);
assert.strictEqual(trie.get('foobar'), 3);
assert.strictEqual(trie.get('foobaz'), undefined);
assert.strictEqual(trie.get('foobarr'), undefined);
assert.equal(trie.findSubstr('fo'), undefined);
assert.equal(trie.findSubstr('foo'), 1);
assert.equal(trie.findSubstr('foooo'), 1);
assert.strictEqual(trie.findSubstr('fo'), undefined);
assert.strictEqual(trie.findSubstr('foo'), 1);
assert.strictEqual(trie.findSubstr('foooo'), 1);
trie.delete('foobar');
trie.delete('bar');
assert.equal(trie.get('foobar'), undefined);
assert.equal(trie.get('bar'), undefined);
assert.strictEqual(trie.get('foobar'), undefined);
assert.strictEqual(trie.get('bar'), undefined);
trie.set('foobar', 17);
trie.set('barr', 18);
assert.equal(trie.get('foobar'), 17);
assert.equal(trie.get('barr'), 18);
assert.equal(trie.get('bar'), undefined);
assert.strictEqual(trie.get('foobar'), 17);
assert.strictEqual(trie.get('barr'), 18);
assert.strictEqual(trie.get('bar'), undefined);
});
test('TernarySearchTree - delete & cleanup', function () {
@@ -576,20 +576,20 @@ suite('Map', () => {
trie.set('/user/foo', 2);
trie.set('/user/foo/flip/flop', 3);
assert.equal(trie.get('/user/foo/bar'), 1);
assert.equal(trie.get('/user/foo'), 2);
assert.equal(trie.get('/user//foo'), 2);
assert.equal(trie.get('/user\\foo'), 2);
assert.equal(trie.get('/user/foo/flip/flop'), 3);
assert.strictEqual(trie.get('/user/foo/bar'), 1);
assert.strictEqual(trie.get('/user/foo'), 2);
assert.strictEqual(trie.get('/user//foo'), 2);
assert.strictEqual(trie.get('/user\\foo'), 2);
assert.strictEqual(trie.get('/user/foo/flip/flop'), 3);
assert.equal(trie.findSubstr('/user/bar'), undefined);
assert.equal(trie.findSubstr('/user/foo'), 2);
assert.equal(trie.findSubstr('\\user\\foo'), 2);
assert.equal(trie.findSubstr('/user//foo'), 2);
assert.equal(trie.findSubstr('/user/foo/ba'), 2);
assert.equal(trie.findSubstr('/user/foo/far/boo'), 2);
assert.equal(trie.findSubstr('/user/foo/bar'), 1);
assert.equal(trie.findSubstr('/user/foo/bar/far/boo'), 1);
assert.strictEqual(trie.findSubstr('/user/bar'), undefined);
assert.strictEqual(trie.findSubstr('/user/foo'), 2);
assert.strictEqual(trie.findSubstr('\\user\\foo'), 2);
assert.strictEqual(trie.findSubstr('/user//foo'), 2);
assert.strictEqual(trie.findSubstr('/user/foo/ba'), 2);
assert.strictEqual(trie.findSubstr('/user/foo/far/boo'), 2);
assert.strictEqual(trie.findSubstr('/user/foo/bar'), 1);
assert.strictEqual(trie.findSubstr('/user/foo/bar/far/boo'), 1);
});
test('TernarySearchTree (PathSegments) - lookup', function () {
@@ -599,11 +599,11 @@ suite('Map', () => {
map.set('/user/foo', 2);
map.set('/user/foo/flip/flop', 3);
assert.equal(map.get('/foo'), undefined);
assert.equal(map.get('/user'), undefined);
assert.equal(map.get('/user/foo'), 2);
assert.equal(map.get('/user/foo/bar'), 1);
assert.equal(map.get('/user/foo/bar/boo'), undefined);
assert.strictEqual(map.get('/foo'), undefined);
assert.strictEqual(map.get('/user'), undefined);
assert.strictEqual(map.get('/user/foo'), 2);
assert.strictEqual(map.get('/user/foo/bar'), 1);
assert.strictEqual(map.get('/user/foo/bar/boo'), undefined);
});
test('TernarySearchTree (PathSegments) - superstr', function () {
@@ -618,31 +618,31 @@ suite('Map', () => {
let iter = map.findSuperstr('/user');
item = iter!.next();
assert.equal(item.value[1], 2);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 2);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value[1], 1);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 1);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value[1], 3);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 3);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
iter = map.findSuperstr('/usr');
item = iter!.next();
assert.equal(item.value[1], 4);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 4);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
assert.equal(map.findSuperstr('/not'), undefined);
assert.equal(map.findSuperstr('/us'), undefined);
assert.equal(map.findSuperstr('/usrr'), undefined);
assert.equal(map.findSuperstr('/userr'), undefined);
assert.strictEqual(map.findSuperstr('/not'), undefined);
assert.strictEqual(map.findSuperstr('/us'), undefined);
assert.strictEqual(map.findSuperstr('/usrr'), undefined);
assert.strictEqual(map.findSuperstr('/userr'), undefined);
});
@@ -688,16 +688,16 @@ suite('Map', () => {
trie.set(URI.file('/user/foo'), 2);
trie.set(URI.file('/user/foo/flip/flop'), 3);
assert.equal(trie.get(URI.file('/user/foo/bar')), 1);
assert.equal(trie.get(URI.file('/user/foo')), 2);
assert.equal(trie.get(URI.file('/user/foo/flip/flop')), 3);
assert.strictEqual(trie.get(URI.file('/user/foo/bar')), 1);
assert.strictEqual(trie.get(URI.file('/user/foo')), 2);
assert.strictEqual(trie.get(URI.file('/user/foo/flip/flop')), 3);
assert.equal(trie.findSubstr(URI.file('/user/bar')), undefined);
assert.equal(trie.findSubstr(URI.file('/user/foo')), 2);
assert.equal(trie.findSubstr(URI.file('/user/foo/ba')), 2);
assert.equal(trie.findSubstr(URI.file('/user/foo/far/boo')), 2);
assert.equal(trie.findSubstr(URI.file('/user/foo/bar')), 1);
assert.equal(trie.findSubstr(URI.file('/user/foo/bar/far/boo')), 1);
assert.strictEqual(trie.findSubstr(URI.file('/user/bar')), undefined);
assert.strictEqual(trie.findSubstr(URI.file('/user/foo')), 2);
assert.strictEqual(trie.findSubstr(URI.file('/user/foo/ba')), 2);
assert.strictEqual(trie.findSubstr(URI.file('/user/foo/far/boo')), 2);
assert.strictEqual(trie.findSubstr(URI.file('/user/foo/bar')), 1);
assert.strictEqual(trie.findSubstr(URI.file('/user/foo/bar/far/boo')), 1);
});
test('TernarySearchTree (URI) - lookup', function () {
@@ -708,23 +708,23 @@ suite('Map', () => {
map.set(URI.parse('http://foo.bar/user/foo?QUERY'), 3);
map.set(URI.parse('http://foo.bar/user/foo/flip/flop'), 3);
assert.equal(map.get(URI.parse('http://foo.bar/foo')), undefined);
assert.equal(map.get(URI.parse('http://foo.bar/user')), undefined);
assert.equal(map.get(URI.parse('http://foo.bar/user/foo/bar')), 1);
assert.equal(map.get(URI.parse('http://foo.bar/user/foo?query')), 2);
assert.equal(map.get(URI.parse('http://foo.bar/user/foo?Query')), undefined);
assert.equal(map.get(URI.parse('http://foo.bar/user/foo?QUERY')), 3);
assert.equal(map.get(URI.parse('http://foo.bar/user/foo/bar/boo')), undefined);
assert.strictEqual(map.get(URI.parse('http://foo.bar/foo')), undefined);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user')), undefined);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user/foo/bar')), 1);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user/foo?query')), 2);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user/foo?Query')), undefined);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user/foo?QUERY')), 3);
assert.strictEqual(map.get(URI.parse('http://foo.bar/user/foo/bar/boo')), undefined);
});
test('TernarySearchTree (URI) - lookup, casing', function () {
const map = new TernarySearchTree<URI, number>(new UriIterator(uri => /^https?$/.test(uri.scheme)));
map.set(URI.parse('http://foo.bar/user/foo/bar'), 1);
assert.equal(map.get(URI.parse('http://foo.bar/USER/foo/bar')), 1);
assert.strictEqual(map.get(URI.parse('http://foo.bar/USER/foo/bar')), 1);
map.set(URI.parse('foo://foo.bar/user/foo/bar'), 1);
assert.equal(map.get(URI.parse('foo://foo.bar/USER/foo/bar')), undefined);
assert.strictEqual(map.get(URI.parse('foo://foo.bar/USER/foo/bar')), undefined);
});
test('TernarySearchTree (URI) - superstr', function () {
@@ -739,48 +739,48 @@ suite('Map', () => {
let iter = map.findSuperstr(URI.file('/user'))!;
item = iter.next();
assert.equal(item.value[1], 2);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 2);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value[1], 1);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 1);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value[1], 3);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 3);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
iter = map.findSuperstr(URI.file('/usr'))!;
item = iter.next();
assert.equal(item.value[1], 4);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 4);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
iter = map.findSuperstr(URI.file('/'))!;
item = iter.next();
assert.equal(item.value[1], 2);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 2);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value[1], 1);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 1);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value[1], 3);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 3);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value[1], 4);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 4);
assert.strictEqual(item.done, false);
item = iter.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
assert.equal(map.findSuperstr(URI.file('/not')), undefined);
assert.equal(map.findSuperstr(URI.file('/us')), undefined);
assert.equal(map.findSuperstr(URI.file('/usrr')), undefined);
assert.equal(map.findSuperstr(URI.file('/userr')), undefined);
assert.strictEqual(map.findSuperstr(URI.file('/not')), undefined);
assert.strictEqual(map.findSuperstr(URI.file('/us')), undefined);
assert.strictEqual(map.findSuperstr(URI.file('/usrr')), undefined);
assert.strictEqual(map.findSuperstr(URI.file('/userr')), undefined);
});
test('TernarySearchTree (ConfigKeySegments) - basics', function () {
@@ -790,16 +790,16 @@ suite('Map', () => {
trie.set('config.foo', 2);
trie.set('config.foo.flip.flop', 3);
assert.equal(trie.get('config.foo.bar'), 1);
assert.equal(trie.get('config.foo'), 2);
assert.equal(trie.get('config.foo.flip.flop'), 3);
assert.strictEqual(trie.get('config.foo.bar'), 1);
assert.strictEqual(trie.get('config.foo'), 2);
assert.strictEqual(trie.get('config.foo.flip.flop'), 3);
assert.equal(trie.findSubstr('config.bar'), undefined);
assert.equal(trie.findSubstr('config.foo'), 2);
assert.equal(trie.findSubstr('config.foo.ba'), 2);
assert.equal(trie.findSubstr('config.foo.far.boo'), 2);
assert.equal(trie.findSubstr('config.foo.bar'), 1);
assert.equal(trie.findSubstr('config.foo.bar.far.boo'), 1);
assert.strictEqual(trie.findSubstr('config.bar'), undefined);
assert.strictEqual(trie.findSubstr('config.foo'), 2);
assert.strictEqual(trie.findSubstr('config.foo.ba'), 2);
assert.strictEqual(trie.findSubstr('config.foo.far.boo'), 2);
assert.strictEqual(trie.findSubstr('config.foo.bar'), 1);
assert.strictEqual(trie.findSubstr('config.foo.bar.far.boo'), 1);
});
test('TernarySearchTree (ConfigKeySegments) - lookup', function () {
@@ -809,11 +809,11 @@ suite('Map', () => {
map.set('config.foo', 2);
map.set('config.foo.flip.flop', 3);
assert.equal(map.get('foo'), undefined);
assert.equal(map.get('config'), undefined);
assert.equal(map.get('config.foo'), 2);
assert.equal(map.get('config.foo.bar'), 1);
assert.equal(map.get('config.foo.bar.boo'), undefined);
assert.strictEqual(map.get('foo'), undefined);
assert.strictEqual(map.get('config'), undefined);
assert.strictEqual(map.get('config.foo'), 2);
assert.strictEqual(map.get('config.foo.bar'), 1);
assert.strictEqual(map.get('config.foo.bar.boo'), undefined);
});
test('TernarySearchTree (ConfigKeySegments) - superstr', function () {
@@ -828,21 +828,21 @@ suite('Map', () => {
let iter = map.findSuperstr('config');
item = iter!.next();
assert.equal(item.value[1], 2);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 2);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value[1], 1);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 1);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value[1], 3);
assert.equal(item.done, false);
assert.strictEqual(item.value[1], 3);
assert.strictEqual(item.done, false);
item = iter!.next();
assert.equal(item.value, undefined);
assert.equal(item.done, true);
assert.strictEqual(item.value, undefined);
assert.strictEqual(item.done, true);
assert.equal(map.findSuperstr('foo'), undefined);
assert.equal(map.findSuperstr('config.foo.no'), undefined);
assert.equal(map.findSuperstr('config.foop'), undefined);
assert.strictEqual(map.findSuperstr('foo'), undefined);
assert.strictEqual(map.findSuperstr('config.foo.no'), undefined);
assert.strictEqual(map.findSuperstr('config.foop'), undefined);
});
@@ -891,7 +891,7 @@ suite('Map', () => {
const resource5 = URI.parse('some://5');
const resource6 = URI.parse('some://6');
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
let res = map.set(resource1, 1);
assert.ok(res === map);
@@ -899,13 +899,13 @@ suite('Map', () => {
map.set(resource3, true);
const values = [...map.values()];
assert.equal(values[0], 1);
assert.equal(values[1], '2');
assert.equal(values[2], true);
assert.strictEqual(values[0], 1);
assert.strictEqual(values[1], '2');
assert.strictEqual(values[2], true);
let counter = 0;
map.forEach((value, key, mapObj) => {
assert.equal(value, values[counter++]);
assert.strictEqual(value, values[counter++]);
assert.ok(URI.isUri(key));
assert.ok(map === mapObj);
});
@@ -916,23 +916,23 @@ suite('Map', () => {
const date = Date.now();
map.set(resource5, date);
assert.equal(map.size, 5);
assert.equal(map.get(resource1), 1);
assert.equal(map.get(resource2), '2');
assert.equal(map.get(resource3), true);
assert.equal(map.get(resource4), obj);
assert.equal(map.get(resource5), date);
assert.strictEqual(map.size, 5);
assert.strictEqual(map.get(resource1), 1);
assert.strictEqual(map.get(resource2), '2');
assert.strictEqual(map.get(resource3), true);
assert.strictEqual(map.get(resource4), obj);
assert.strictEqual(map.get(resource5), date);
assert.ok(!map.get(resource6));
map.delete(resource6);
assert.equal(map.size, 5);
assert.strictEqual(map.size, 5);
assert.ok(map.delete(resource1));
assert.ok(map.delete(resource2));
assert.ok(map.delete(resource3));
assert.ok(map.delete(resource4));
assert.ok(map.delete(resource5));
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
assert.ok(!map.get(resource5));
assert.ok(!map.get(resource4));
assert.ok(!map.get(resource3));
@@ -944,13 +944,13 @@ suite('Map', () => {
map.set(resource3, true);
assert.ok(map.has(resource1));
assert.equal(map.get(resource1), 1);
assert.equal(map.get(resource2), '2');
assert.equal(map.get(resource3), true);
assert.strictEqual(map.get(resource1), 1);
assert.strictEqual(map.get(resource2), '2');
assert.strictEqual(map.get(resource3), true);
map.clear();
assert.equal(map.size, 0);
assert.strictEqual(map.size, 0);
assert.ok(!map.get(resource1));
assert.ok(!map.get(resource2));
assert.ok(!map.get(resource3));
@@ -971,16 +971,16 @@ suite('Map', () => {
const fileAUpper = URI.parse('file://SOME/FILEA');
map.set(fileA, 'true');
assert.equal(map.get(fileA), 'true');
assert.strictEqual(map.get(fileA), 'true');
assert.ok(!map.get(fileAUpper));
assert.ok(!map.get(fileB));
map.set(fileAUpper, 'false');
assert.equal(map.get(fileAUpper), 'false');
assert.strictEqual(map.get(fileAUpper), 'false');
assert.equal(map.get(fileA), 'true');
assert.strictEqual(map.get(fileA), 'true');
const windowsFile = URI.file('c:\\test with %25\\c#code');
const uncFile = URI.file('\\\\shäres\\path\\c#\\plugin.json');
@@ -988,8 +988,8 @@ suite('Map', () => {
map.set(windowsFile, 'true');
map.set(uncFile, 'true');
assert.equal(map.get(windowsFile), 'true');
assert.equal(map.get(uncFile), 'true');
assert.strictEqual(map.get(windowsFile), 'true');
assert.strictEqual(map.get(uncFile), 'true');
});
test('ResourceMap - files (ignorecase)', function () {
@@ -1000,16 +1000,16 @@ suite('Map', () => {
const fileAUpper = URI.parse('file://SOME/FILEA');
map.set(fileA, 'true');
assert.equal(map.get(fileA), 'true');
assert.strictEqual(map.get(fileA), 'true');
assert.equal(map.get(fileAUpper), 'true');
assert.strictEqual(map.get(fileAUpper), 'true');
assert.ok(!map.get(fileB));
map.set(fileAUpper, 'false');
assert.equal(map.get(fileAUpper), 'false');
assert.strictEqual(map.get(fileAUpper), 'false');
assert.equal(map.get(fileA), 'false');
assert.strictEqual(map.get(fileA), 'false');
const windowsFile = URI.file('c:\\test with %25\\c#code');
const uncFile = URI.file('\\\\shäres\\path\\c#\\plugin.json');
@@ -1017,7 +1017,7 @@ suite('Map', () => {
map.set(windowsFile, 'true');
map.set(uncFile, 'true');
assert.equal(map.get(windowsFile), 'true');
assert.equal(map.get(uncFile), 'true');
assert.strictEqual(map.get(windowsFile), 'true');
assert.strictEqual(map.get(uncFile), 'true');
});
});
+1 -1
View File
@@ -73,7 +73,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
}
// Signal exit to shared process when shutting down
if (!window.webContents.isDestroyed()) {
if (!window.isDestroyed() && !window.webContents.isDestroyed()) {
window.webContents.send('vscode:electron-main->shared-process=exit');
}
+2 -2
View File
@@ -422,7 +422,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.dispose();
});
const svgFileSchemes = new Set([Schemas.file, Schemas.vscodeFileResource, 'devtools']);
const svgFileSchemes = new Set([Schemas.file, Schemas.vscodeFileResource, Schemas.vscodeRemoteResource, 'devtools']);
this._win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
// Prevent loading of remote svgs
if (details.url.endsWith('.svg')) {
@@ -1265,7 +1265,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
send(channel: string, ...args: any[]): void {
if (this._win) {
if (this._win.webContents.isDestroyed()) {
if (this._win.isDestroyed() || this._win.webContents.isDestroyed()) {
this.logService.warn(`Sending IPC message to channel ${channel} for window that is destroyed`);
return;
}
+1 -1
View File
@@ -47,7 +47,7 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { toErrorMessage } from 'vs/base/common/errorMessage';
export class CliMain extends Disposable {
class CliMain extends Disposable {
constructor(
private argv: NativeParsedArgs
@@ -255,7 +255,7 @@ export class ViewLayout extends Disposable implements IViewLayout {
let result = this._linesLayout.getLinesTotalHeight();
if (options.get(EditorOption.scrollBeyondLastLine)) {
result += height - options.get(EditorOption.lineHeight);
result += Math.max(0, height - options.get(EditorOption.lineHeight) - options.get(EditorOption.padding).bottom);
} else {
result += this._getHorizontalScrollbarHeight(width, contentWidth);
}
+2 -1
View File
@@ -27,7 +27,8 @@ const supportsCopy = (platform.isNative || document.queryCommandSupported('copy'
const supportsCopyWithSyntaxHighlighting = (supportsCopy && !browser.isEdge);
// Firefox only supports navigator.clipboard.readText() in browser extensions.
// See https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText#Browser_compatibility
const supportsPaste = (browser.isFirefox ? document.queryCommandSupported('paste') : true);
// When loading over http, navigator.clipboard can be undefined. See https://github.com/microsoft/monaco-editor/issues/2313
const supportsPaste = (typeof navigator.clipboard === 'undefined' || browser.isFirefox) ? document.queryCommandSupported('paste') : true;
function registerCommand<T extends Command>(command: T): T {
command.register();
@@ -25,7 +25,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { CancellationToken } from 'vs/base/common/cancellation';
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
import { getErrorMessage } from 'vs/base/common/errors';
import { forEach, IStringDictionary } from 'vs/base/common/collections';
import { IStringDictionary } from 'vs/base/common/collections';
import { IExtensionsStorageSyncService } from 'vs/platform/userDataSync/common/extensionsStorageSync';
interface IExtensionResourceMergeResult extends IAcceptResult {
@@ -451,9 +451,9 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const extensionState = getExtensionStorageState(publisher, name, this.storageService);
const keys = version ? this.extensionsStorageSyncService.getKeysForSync({ id: getGalleryExtensionId(publisher, name), version }) : undefined;
if (keys) {
keys.forEach(key => extensionState[key] = state[key]);
keys.forEach(key => { extensionState[key] = state[key]; });
} else {
forEach(state, ({ key, value }) => extensionState[key] = value);
Object.keys(state).forEach(key => extensionState[key] = state[key]);
}
storeExtensionStorageState(publisher, name, extensionState, this.storageService);
}
@@ -556,7 +556,7 @@ export class ExtensionsInitializer extends AbstractInitializer {
for (const { syncExtension, installedExtension } of installedExtensionsToSync) {
if (syncExtension.state) {
const extensionState = getExtensionStorageState(installedExtension.manifest.publisher, installedExtension.manifest.name, this.storageService);
forEach(syncExtension.state, ({ key, value }) => extensionState[key] = value);
Object.keys(syncExtension.state).forEach(key => extensionState[key] = syncExtension.state![key]);
storeExtensionStorageState(installedExtension.manifest.publisher, installedExtension.manifest.name, extensionState, this.storageService);
}
}
-2
View File
@@ -11944,8 +11944,6 @@ declare module 'vscode' {
export const onDidChange: Event<void>;
}
//#region Comments
/**
* Collapsible state of a [comment thread](#CommentThread)
*/
+16 -6
View File
@@ -131,6 +131,7 @@ declare module 'vscode' {
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region @alexdima - resolvers
export interface MessageOptions {
@@ -728,6 +729,7 @@ declare module 'vscode' {
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region debug
/**
@@ -748,6 +750,7 @@ declare module 'vscode' {
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region @joaomoreno: SCM validation
/**
@@ -798,6 +801,7 @@ declare module 'vscode' {
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region @joaomoreno: SCM selected provider
export interface SourceControl {
@@ -873,6 +877,7 @@ declare module 'vscode' {
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region @jrieken -> exclusive document filters
export interface DocumentFilter {
@@ -984,7 +989,7 @@ declare module 'vscode' {
//#endregion
//#region @rebornix: Notebook
//#region notebook https://github.com/microsoft/vscode/issues/106744
export enum CellKind {
Markdown = 1,
@@ -2445,7 +2450,7 @@ declare module 'vscode' {
/**
* The uri that triggered the open.
*
* Due to port forwarding, this may not match the `resolvedUri` passed to `openExternalUri`
* Due to port forwarding, this may not match the `resolvedUri` passed to `openExternalUri`.
*/
readonly sourceUri: Uri;
}
@@ -2455,6 +2460,13 @@ declare module 'vscode' {
*/
interface ExternalUriOpenerMetadata {
/**
* List of uri schemes the opener is triggered for.
*
* Currently only `http` and `https` are supported.
*/
readonly schemes: readonly string[]
/**
* Text displayed to the user that explains what the opener does.
*
@@ -2471,14 +2483,12 @@ declare module 'vscode' {
*
* @param id Unique id of the opener, such as `myExtension.browserPreview`. This is used in settings
* and commands to identify the opener.
* @param schemes List of uri schemes the opener is triggered for. Currently only `http`
* and `https` are supported.
* @param opener Opener to register.
* @param metadata Additional information about the opener.
*
* @returns Disposable that unregisters the opener.
*/
export function registerExternalUriOpener(id: string, schemes: readonly string[], opener: ExternalUriOpener, metadata: ExternalUriOpenerMetadata): Disposable;
*/
export function registerExternalUriOpener(id: string, opener: ExternalUriOpener, metadata: ExternalUriOpenerMetadata): Disposable;
}
interface OpenExternalOptions {
@@ -681,9 +681,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.showNotebookDocument(document, options);
},
registerExternalUriOpener(id: string, schemes: readonly string[], opener: vscode.ExternalUriOpener, metadata: vscode.ExternalUriOpenerMetadata) {
registerExternalUriOpener(id: string, opener: vscode.ExternalUriOpener, metadata: vscode.ExternalUriOpenerMetadata) {
checkProposedApiEnabled(extension);
return extHostUriOpeners.registerUriOpener(extension.identifier, id, schemes, opener, metadata);
return extHostUriOpeners.registerUriOpener(extension.identifier, id, opener, metadata);
},
get openEditors() {
checkProposedApiEnabled(extension);
@@ -1798,7 +1798,7 @@ export interface ExtHostNotebookShape {
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
$backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<string | undefined>;
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined }): void;
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelFriendlyId: string | undefined }): void;
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void;
$acceptModelSaved(uriComponents: UriComponents): void;
+23 -22
View File
@@ -78,8 +78,8 @@ export interface ExtHostNotebookOutputRenderingHandler {
}
export class ExtHostNotebookKernelProviderAdapter extends Disposable {
private _kernelToId = new Map<vscode.NotebookKernel, string>();
private _idToKernel = new Map<string, vscode.NotebookKernel>();
private _kernelToFriendlyId = new Map<vscode.NotebookKernel, string>();
private _friendlyIdToKernel = new Map<string, vscode.NotebookKernel>();
constructor(
private readonly _proxy: MainThreadNotebookShape,
private readonly _handle: number,
@@ -101,24 +101,25 @@ export class ExtHostNotebookKernelProviderAdapter extends Disposable {
const newMap = new Map<vscode.NotebookKernel, string>();
let kernel_unique_pool = 0;
const kernelIdCache = new Set<string>();
const kernelFriendlyIdCache = new Set<string>();
const transformedData: INotebookKernelInfoDto2[] = data.map(kernel => {
let id = this._kernelToId.get(kernel);
if (id === undefined) {
if (kernel.id && kernelIdCache.has(kernel.id)) {
id = `${this._extension.identifier.value}_${kernel.id}_${kernel_unique_pool++}`;
let friendlyId = this._kernelToFriendlyId.get(kernel);
if (friendlyId === undefined) {
if (kernel.id && kernelFriendlyIdCache.has(kernel.id)) {
friendlyId = `${this._extension.identifier.value}_${kernel.id}_${kernel_unique_pool++}`;
} else {
id = `${this._extension.identifier.value}_${kernel.id || UUID.generateUuid()}`;
friendlyId = `${this._extension.identifier.value}_${kernel.id || UUID.generateUuid()}`;
}
this._kernelToId.set(kernel, id);
this._kernelToFriendlyId.set(kernel, friendlyId);
}
newMap.set(kernel, id);
newMap.set(kernel, friendlyId);
return {
id,
id: kernel.id,
friendlyId: friendlyId,
label: kernel.label,
extension: this._extension.identifier,
extensionLocation: this._extension.extensionLocation,
@@ -129,22 +130,22 @@ export class ExtHostNotebookKernelProviderAdapter extends Disposable {
};
});
this._kernelToId = newMap;
this._kernelToFriendlyId = newMap;
this._idToKernel.clear();
this._kernelToId.forEach((value, key) => {
this._idToKernel.set(value, key);
this._friendlyIdToKernel.clear();
this._kernelToFriendlyId.forEach((value, key) => {
this._friendlyIdToKernel.set(value, key);
});
return transformedData;
}
getKernel(kernelId: string) {
return this._idToKernel.get(kernelId);
getKernelByFriendlyId(kernelId: string) {
return this._friendlyIdToKernel.get(kernelId);
}
async resolveNotebook(kernelId: string, document: ExtHostNotebookDocument, webview: vscode.NotebookCommunication, token: CancellationToken) {
const kernel = this._idToKernel.get(kernelId);
const kernel = this._friendlyIdToKernel.get(kernelId);
if (kernel && this._provider.resolveKernel) {
return this._provider.resolveKernel(kernel, document.notebookDocument, webview, token);
@@ -152,7 +153,7 @@ export class ExtHostNotebookKernelProviderAdapter extends Disposable {
}
async executeNotebook(kernelId: string, document: ExtHostNotebookDocument, cell: ExtHostCell | undefined) {
const kernel = this._idToKernel.get(kernelId);
const kernel = this._friendlyIdToKernel.get(kernelId);
if (!kernel) {
return;
@@ -166,7 +167,7 @@ export class ExtHostNotebookKernelProviderAdapter extends Disposable {
}
async cancelNotebook(kernelId: string, document: ExtHostNotebookDocument, cell: ExtHostCell | undefined) {
const kernel = this._idToKernel.get(kernelId);
const kernel = this._friendlyIdToKernel.get(kernelId);
if (!kernel) {
return;
@@ -580,10 +581,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
this._outputDisplayOrder = displayOrder;
}
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined; }) {
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelFriendlyId: string | undefined; }) {
if (event.providerHandle !== undefined) {
this._withAdapter(event.providerHandle, event.uri, async (adapter, document) => {
const kernel = event.kernelId ? adapter.getKernel(event.kernelId) : undefined;
const kernel = event.kernelFriendlyId ? adapter.getKernelByFriendlyId(event.kernelFriendlyId) : undefined;
this._editors.forEach(editor => {
if (editor.editor.notebookData === document) {
editor.editor._acceptKernel(kernel);
@@ -12,7 +12,7 @@ import { Emitter, Event } from 'vs/base/common/event';
export class ExtensionSecrets implements vscode.SecretStorage {
protected readonly _id: string;
protected readonly _secretState: ExtHostSecretState;
readonly #secretState: ExtHostSecretState;
private _onDidChange = new Emitter<vscode.SecretStorageChangeEvent>();
readonly onDidChange: Event<vscode.SecretStorageChangeEvent> = this._onDidChange.event;
@@ -20,9 +20,9 @@ export class ExtensionSecrets implements vscode.SecretStorage {
constructor(extensionDescription: IExtensionDescription, secretState: ExtHostSecretState) {
this._id = ExtensionIdentifier.toKey(extensionDescription.identifier);
this._secretState = secretState;
this.#secretState = secretState;
this._secretState.onDidChangePassword(e => {
this.#secretState.onDidChangePassword(e => {
if (e.extensionId === this._id) {
this._onDidChange.fire({ key: e.key });
}
@@ -30,14 +30,14 @@ export class ExtensionSecrets implements vscode.SecretStorage {
}
get(key: string): Promise<string | undefined> {
return this._secretState.get(this._id, key);
return this.#secretState.get(this._id, key);
}
store(key: string, value: string): Promise<void> {
return this._secretState.store(this._id, key, value);
return this.#secretState.store(this._id, key, value);
}
delete(key: string): Promise<void> {
return this._secretState.delete(this._id, key);
return this.#secretState.delete(this._id, key);
}
}
+160 -2
View File
@@ -112,7 +112,10 @@ export class ExtHostTesting implements ExtHostTestingShape {
if (resource === ExtHostTestingResource.TextDocument) {
const document = this.documents.getDocument(uri);
if (document) {
method = p => p.createDocumentTestHierarchy?.(document.document);
const folder = await this.workspace.getWorkspaceFolder2(uri, false);
method = p => p.createDocumentTestHierarchy
? p.createDocumentTestHierarchy(document.document)
: this.createDefaultDocumentTestHierarchy(p, document.document, folder);
}
} else {
const folder = await this.workspace.getWorkspaceFolder2(uri, false);
@@ -190,7 +193,10 @@ export class ExtHostTesting implements ExtHostTestingShape {
return EMPTY_TEST_RESULT;
}
const tests = req.ids.map(id => this.ownedTests.getTestById(id)?.actual).filter(isDefined);
const tests = req.ids.map(id => this.ownedTests.getTestById(id)?.actual)
.filter(isDefined)
// Only send the actual TestItem's to the user to run.
.map(t => t instanceof TestItemFilteredWrapper ? t.actual : t);
if (!tests.length) {
return EMPTY_TEST_RESULT;
}
@@ -217,6 +223,158 @@ export class ExtHostTesting implements ExtHostTestingShape {
const { actual, previousChildren, previousEquals, ...item } = owned;
return Promise.resolve(item);
}
private createDefaultDocumentTestHierarchy(provider: vscode.TestProvider, document: vscode.TextDocument, folder: vscode.WorkspaceFolder | undefined): vscode.TestHierarchy<vscode.TestItem> | undefined {
if (!folder) {
return;
}
const workspaceHierarchy = provider.createWorkspaceTestHierarchy?.(folder);
if (!workspaceHierarchy) {
return;
}
const onDidChangeTest = new Emitter<vscode.TestItem>();
workspaceHierarchy.onDidChangeTest(node => {
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(node, document);
const previouslySeen = wrapper.hasNodeMatchingFilter;
if (previouslySeen) {
// reset cache and get whether you can currently see the TestItem.
wrapper.reset();
const currentlySeen = wrapper.hasNodeMatchingFilter;
if (currentlySeen) {
onDidChangeTest.fire(wrapper);
return;
}
// Fire the event to say that the current visible parent has changed.
onDidChangeTest.fire(wrapper.visibleParent);
return;
}
const previousParent = wrapper.visibleParent;
wrapper.reset();
const currentlySeen = wrapper.hasNodeMatchingFilter;
// It wasn't previously seen and isn't currently seen so
// nothing has actually changed.
if (!currentlySeen) {
return;
}
// The test is now visible so we need to refresh the cache
// of the previous visible parent and fire that it has changed.
previousParent.reset();
onDidChangeTest.fire(previousParent);
});
return {
root: TestItemFilteredWrapper.getWrapperForTestItem(workspaceHierarchy.root, document),
dispose: () => {
onDidChangeTest.dispose();
TestItemFilteredWrapper.removeFilter(document);
},
onDidChangeTest: onDidChangeTest.event
};
}
}
/*
* A class which wraps a vscode.TestItem that provides the ability to filter a TestItem's children
* to only the children that are located in a certain vscode.Uri.
*/
export class TestItemFilteredWrapper implements vscode.TestItem {
private static wrapperMap = new WeakMap<vscode.TextDocument, WeakMap<vscode.TestItem, TestItemFilteredWrapper>>();
public static removeFilter(document: vscode.TextDocument): void {
this.wrapperMap.delete(document);
}
// Wraps the TestItem specified in a TestItemFilteredWrapper and pulls from a cache if it already exists.
public static getWrapperForTestItem(item: vscode.TestItem, filterDocument: vscode.TextDocument, parent?: TestItemFilteredWrapper): TestItemFilteredWrapper {
let innerMap = this.wrapperMap.get(filterDocument);
if (innerMap?.has(item)) {
return innerMap.get(item)!;
}
if (!innerMap) {
innerMap = new WeakMap<vscode.TestItem, TestItemFilteredWrapper>();
this.wrapperMap.set(filterDocument, innerMap);
}
const w = new TestItemFilteredWrapper(item, filterDocument, parent);
innerMap.set(item, w);
return w;
}
public get label() {
return this.actual.label;
}
public get debuggable() {
return this.actual.debuggable;
}
public get description() {
return this.actual.description;
}
public get location() {
return this.actual.location;
}
public get runnable() {
return this.actual.runnable;
}
public get state() {
return this.actual.state;
}
public get children() {
// We only want children that match the filter.
return this.getWrappedChildren().filter(child => child.hasNodeMatchingFilter);
}
public get visibleParent(): TestItemFilteredWrapper {
return this.hasNodeMatchingFilter ? this : this.parent!.visibleParent;
}
private matchesFilter: boolean | undefined;
// Determines if the TestItem matches the filter. This would be true if:
// 1. We don't have a parent (because the root is the workspace root node)
// 2. The URI of the current node matches the filter URI
// 3. Some child of the current node matches the filter URI
public get hasNodeMatchingFilter(): boolean {
if (this.matchesFilter === undefined) {
this.matchesFilter = !this.parent
|| this.actual.location?.uri.toString() === this.filterDocument.uri.toString()
|| this.getWrappedChildren().some(child => child.hasNodeMatchingFilter);
}
return this.matchesFilter;
}
// Reset the cache of whether or not you can see a node from a particular node
// up to it's visible parent.
public reset(): void {
if (this !== this.visibleParent) {
this.parent?.reset();
}
this.matchesFilter = undefined;
}
private constructor(public readonly actual: vscode.TestItem, private filterDocument: vscode.TextDocument, private readonly parent?: TestItemFilteredWrapper) {
this.getWrappedChildren();
}
private getWrappedChildren() {
return this.actual.children?.map(t => TestItemFilteredWrapper.getWrapperForTestItem(t, this.filterDocument, this)) || [];
}
}
/**
+10 -21
View File
@@ -11,18 +11,12 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import type * as vscode from 'vscode';
import { ExtHostUriOpenersShape, IMainContext, MainContext, MainThreadUriOpenersShape } from './extHost.protocol';
interface OpenerEntry {
readonly extension: ExtensionIdentifier;
readonly schemes: ReadonlySet<string>;
readonly opener: vscode.ExternalUriOpener;
readonly metadata: vscode.ExternalUriOpenerMetadata;
}
export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
private readonly _proxy: MainThreadUriOpenersShape;
private readonly _openers = new Map<string, OpenerEntry>();
private readonly _openers = new Map<string, vscode.ExternalUriOpener>();
constructor(
mainContext: IMainContext,
@@ -33,7 +27,6 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
registerUriOpener(
extensionId: ExtensionIdentifier,
id: string,
schemes: readonly string[],
opener: vscode.ExternalUriOpener,
metadata: vscode.ExternalUriOpenerMetadata,
): vscode.Disposable {
@@ -41,13 +34,8 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
throw new Error(`Opener with id already registered: '${id}'`);
}
this._openers.set(id, {
opener,
extension: extensionId,
schemes: new Set(schemes),
metadata
});
this._proxy.$registerUriOpener(id, schemes, extensionId, metadata.label);
this._openers.set(id, opener);
this._proxy.$registerUriOpener(id, metadata.schemes, extensionId, metadata.label);
return toDisposable(() => {
this._openers.delete(id);
@@ -56,21 +44,22 @@ export class ExtHostUriOpeners implements ExtHostUriOpenersShape {
}
async $canOpenUri(id: string, uriComponents: UriComponents, token: CancellationToken): Promise<modes.ExternalUriOpenerPriority> {
const entry = this._openers.get(id);
if (!entry) {
const opener = this._openers.get(id);
if (!opener) {
throw new Error(`Unknown opener with id: ${id}`);
}
const uri = URI.revive(uriComponents);
return entry.opener.canOpenExternalUri(uri, token);
return opener.canOpenExternalUri(uri, token);
}
async $openUri(id: string, context: { resolvedUri: UriComponents, sourceUri: UriComponents }, token: CancellationToken): Promise<void> {
const entry = this._openers.get(id);
if (!entry) {
const opener = this._openers.get(id);
if (!opener) {
throw new Error(`Unknown opener id: '${id}'`);
}
return entry.opener.openExternalUri(URI.revive(context.resolvedUri), {
return opener.openExternalUri(URI.revive(context.resolvedUri), {
sourceUri: URI.revive(context.sourceUri)
}, token);
}
@@ -259,7 +259,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
}
async $applyCandidateFilter(candidates: CandidatePort[]): Promise<CandidatePort[]> {
return Promise.all(candidates.filter(candidate => this._showCandidatePort(candidate.host, candidate.port, candidate.detail)));
const filter = await Promise.all(candidates.map(candidate => this._showCandidatePort(candidate.host, candidate.port, candidate.detail)));
return candidates.filter((candidate, index) => filter[index]);
}
async findCandidatePorts(): Promise<CandidatePort[]> {
@@ -51,12 +51,12 @@ import { isStandalone } from 'vs/base/browser/browser';
'workbench.editor.decorations.badges': {
'type': 'boolean',
'markdownDescription': nls.localize('decorations.badges', "Controls whether editor file decorations should use badges."),
'default': true
'default': false
},
'workbench.editor.decorations.colors': {
'type': 'boolean',
'markdownDescription': nls.localize('decorations.colors', "Controls whether editor file decorations should use colors."),
'default': true
'default': false
},
'workbench.editor.labelFormat': {
'type': 'string',
@@ -19,6 +19,8 @@ import { BulkCellEdits, ResourceNotebookCellEdit } from 'vs/workbench/contrib/bu
import { UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo';
import { LinkedList } from 'vs/base/common/linkedList';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
class BulkEdit {
@@ -119,6 +121,8 @@ export class BulkEditService implements IBulkEditService {
@IInstantiationService private readonly _instaService: IInstantiationService,
@ILogService private readonly _logService: ILogService,
@IEditorService private readonly _editorService: IEditorService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IDialogService private readonly _dialogService: IDialogService
) { }
setPreviewHandler(handler: IBulkEditPreviewHandler): IDisposable {
@@ -176,9 +180,10 @@ export class BulkEditService implements IBulkEditService {
undoRedoGroupRemove = this._activeUndoRedoGroups.push(undoRedoGroup);
}
const label = options?.quotableLabel || options?.label;
const bulkEdit = this._instaService.createInstance(
BulkEdit,
options?.quotableLabel || options?.label,
label,
codeEditor,
options?.progress ?? Progress.None,
options?.token ?? CancellationToken.None,
@@ -189,7 +194,9 @@ export class BulkEditService implements IBulkEditService {
);
try {
const listener = this._lifecycleService.onBeforeShutdown(e => e.veto(this.shouldVeto(label), 'veto.blukEditService'));
await bulkEdit.perform();
listener.dispose();
return { ariaSummary: bulkEdit.ariaMessage() };
} catch (err) {
// console.log('apply FAILED');
@@ -200,6 +207,16 @@ export class BulkEditService implements IBulkEditService {
undoRedoGroupRemove();
}
}
private async shouldVeto(label: string | undefined): Promise<boolean> {
label = label || localize('fileOperation', "File operation");
const result = await this._dialogService.confirm({
message: localize('areYouSureQuiteBulkEdit', "Are you sure you want to quit? '{0}' is in progress.", label),
primaryButton: localize('quit', "Quit")
});
return !result.confirmed;
}
}
registerSingleton(IBulkEditService, BulkEditService, true);
@@ -2104,7 +2104,7 @@ CommandsRegistry.registerCommand('_resolveNotebookKernels', async (accessor, arg
source.dispose();
return kernels.map(provider => ({
id: provider.id,
id: provider.friendlyId,
label: provider.label,
description: provider.description,
detail: provider.detail,
@@ -33,11 +33,33 @@ registerAction2(class extends Action2 {
title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' },
precondition: NOTEBOOK_IS_ACTIVE_EDITOR,
icon: selectKernelIcon,
f1: true
f1: true,
description: {
description: nls.localize('notebookActions.selectKernel.args', "Notebook Kernel Args"),
args: [
{
name: 'kernelInfo',
description: 'The kernel info',
schema: {
'type': 'object',
'required': ['id', 'extension'],
'properties': {
'id': {
'type': 'string'
},
'extension': {
'type': 'string'
}
}
}
}
]
},
});
}
async run(accessor: ServicesAccessor, context?: { id: string }): Promise<void> {
async run(accessor: ServicesAccessor, context?: { id: string, extension: string }): Promise<void> {
const editorService = accessor.get<IEditorService>(IEditorService);
const quickInputService = accessor.get<IQuickInputService>(IQuickInputService);
const configurationService = accessor.get<IConfigurationService>(IConfigurationService);
@@ -64,9 +86,11 @@ registerAction2(class extends Action2 {
const tokenSource = new CancellationTokenSource();
const availableKernels = await editor.beginComputeContributedKernels();
if (availableKernels.length && availableKernels.find(kernel => kernel.id === context?.id)) {
const selectedKernel = availableKernels.find(kernel => kernel.id === context?.id);
const selectedKernel = availableKernels.length ? availableKernels.find(
kernel => kernel.id && context?.id && kernel.id === context?.id && kernel.extension.value === context?.extension
) : undefined;
if (selectedKernel) {
editor.activeKernel = selectedKernel!;
return selectedKernel!.resolve(editor.uri!, editor.getId(), tokenSource.token);
} else {
@@ -75,13 +99,13 @@ registerAction2(class extends Action2 {
const picks: QuickPickInput<IQuickPickItem & { run(): void; kernelProviderId?: string; }>[] = [...availableKernels].map((a) => {
return {
id: a.id,
id: a.friendlyId,
label: a.label,
picked: a.id === activeKernel?.id,
picked: a.friendlyId === activeKernel?.friendlyId,
description:
a.description
? a.description
: a.extension.value + (a.id === activeKernel?.id
: a.extension.value + (a.friendlyId === activeKernel?.friendlyId
? nls.localize('currentActiveKernel', " (Currently Active)")
: ''),
detail: a.detail,
@@ -175,9 +175,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._activeKernelResolvePromise = undefined;
const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
memento[this.viewModel.viewType] = this._activeKernel?.id;
memento[this.viewModel.viewType] = this._activeKernel?.friendlyId;
this._activeKernelMemento.saveMemento();
this._onDidChangeKernel.fire();
if (this._activeKernel) {
this._loadKernelPreloads(this._activeKernel.extensionLocation, this._activeKernel);
}
}
private _activeKernelResolvePromise: Promise<void> | undefined = undefined;
@@ -771,7 +774,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this.multipleKernelsAvailable = false;
}
const activeKernelStillExist = [...availableKernels].find(kernel => kernel.id === this.activeKernel?.id && this.activeKernel?.id !== undefined);
const activeKernelStillExist = [...availableKernels].find(kernel => kernel.friendlyId === this.activeKernel?.friendlyId && this.activeKernel?.friendlyId !== undefined);
if (activeKernelStillExist) {
// the kernel still exist, we don't want to modify the selection otherwise user's temporary preference is lost
@@ -797,7 +800,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const cachedKernelId = memento[provider.id];
this.activeKernel =
filteredKernels.find(kernel => kernel.isPreferred)
|| filteredKernels.find(kernel => kernel.id === cachedKernelId)
|| filteredKernels.find(kernel => kernel.friendlyId === cachedKernelId)
|| filteredKernels[0];
} else {
this.activeKernel = undefined;
@@ -818,7 +821,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
}
memento[provider.id] = this._activeKernel?.id;
memento[provider.id] = this._activeKernel?.friendlyId;
this._activeKernelMemento.saveMemento();
tokenSource.dispose();
@@ -831,7 +834,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const cachedKernelId = memento[provider.id];
const preferedKernel = kernelsFromSameExtension.find(kernel => kernel.isPreferred)
|| kernelsFromSameExtension.find(kernel => kernel.id === cachedKernelId)
|| kernelsFromSameExtension.find(kernel => kernel.friendlyId === cachedKernelId)
|| kernelsFromSameExtension[0];
this.activeKernel = preferedKernel;
if (this.activeKernel) {
@@ -848,7 +851,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
return;
}
memento[provider.id] = this._activeKernel?.id;
memento[provider.id] = this._activeKernel?.friendlyId;
this._activeKernelMemento.saveMemento();
tokenSource.dispose();
return;
@@ -1673,7 +1676,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const availableKernels = await this.beginComputeContributedKernels();
const picks: QuickPickInput<IQuickPickItem & { run(): void; kernelProviderId?: string; }>[] = availableKernels.map((a) => {
return {
id: a.id,
id: a.friendlyId,
label: a.label,
picked: false,
description:
@@ -270,8 +270,8 @@ export class NotebookService extends Disposable implements INotebookService, ICu
private readonly _onDidChangeKernels = new Emitter<URI | undefined>();
onDidChangeKernels: Event<URI | undefined> = this._onDidChangeKernels.event;
private readonly _onDidChangeNotebookActiveKernel = new Emitter<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }>();
onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }> = this._onDidChangeNotebookActiveKernel.event;
private readonly _onDidChangeNotebookActiveKernel = new Emitter<{ uri: URI, providerHandle: number | undefined, kernelFriendlyId: string | undefined; }>();
onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelFriendlyId: string | undefined; }> = this._onDidChangeNotebookActiveKernel.event;
private cutItems: NotebookCellTextModel[] | undefined;
private _lastClipboardIsCopy: boolean = true;
@@ -696,9 +696,10 @@ export class NotebookService extends Disposable implements INotebookService, ICu
const data = await provider.provideKernels(resource, token);
result[index] = data.map(dto => {
return {
id: dto.id,
extension: dto.extension,
extensionLocation: URI.revive(dto.extensionLocation),
id: dto.id,
friendlyId: dto.friendlyId,
label: dto.label,
description: dto.description,
detail: dto.detail,
@@ -706,13 +707,13 @@ export class NotebookService extends Disposable implements INotebookService, ICu
preloads: dto.preloads,
providerHandle: dto.providerHandle,
resolve: async (uri: URI, editorId: string, token: CancellationToken) => {
return provider.resolveKernel(editorId, uri, dto.id, token);
return provider.resolveKernel(editorId, uri, dto.friendlyId, token);
},
executeNotebookCell: async (uri: URI, handle: number | undefined) => {
return provider.executeNotebook(uri, dto.id, handle);
return provider.executeNotebook(uri, dto.friendlyId, handle);
},
cancelNotebookCell: (uri: URI, handle: number | undefined): Promise<void> => {
return provider.cancelNotebook(uri, dto.id, handle);
return provider.cancelNotebook(uri, dto.friendlyId, handle);
}
};
});
@@ -922,7 +923,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu
this._onDidChangeNotebookActiveKernel.fire({
uri: editor.uri!,
providerHandle: editor.activeKernel?.providerHandle,
kernelId: editor.activeKernel?.id
kernelFriendlyId: editor.activeKernel?.friendlyId
});
}));
}
@@ -143,8 +143,11 @@ export class StatefulMarkdownCell extends Disposable {
// active cell and no run status
if (this._activeCellRunPlaceholder === null) {
// const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID);
this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(getExecuteCellPlaceholder(this.viewCell));
this._register(this._activeCellRunPlaceholder);
const placeholder = getExecuteCellPlaceholder(this.viewCell);
if (!this.notebookCellStatusBarService.getEntries(this.viewCell.uri).find(entry => entry.text === placeholder.text && entry.command === placeholder.command)) {
this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(placeholder);
this._register(this._activeCellRunPlaceholder);
}
}
return;
@@ -334,8 +337,9 @@ export class StatefulMarkdownCell extends Disposable {
}
);
this.viewCell.editorHeight = realContentHeight;
this.relayoutCell();
// LET the content size observer to handle it
// this.viewCell.editorHeight = realContentHeight;
// this.relayoutCell();
}
private relayoutCell(): void {
@@ -787,7 +787,8 @@ export function notebookDocumentFilterMatch(filter: INotebookDocumentFilter, vie
}
export interface INotebookKernelInfoDto2 {
id: string;
id?: string;
friendlyId: string;
label: string;
extension: ExtensionIdentifier;
extensionLocation: URI;
@@ -46,7 +46,7 @@ export interface INotebookService {
onDidAddNotebookDocument: Event<NotebookTextModel>;
onNotebookDocumentSaved: Event<URI>;
onDidChangeKernels: Event<URI | undefined>;
onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined; }>;
onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelFriendlyId: string | undefined; }>;
registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable;
getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[];
@@ -18,7 +18,8 @@ import { ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedH
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import type { IThemable } from 'vs/base/common/styler';
import { Codicon } from 'vs/base/common/codicons';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ISearchConfiguration } from 'vs/workbench/services/search/common/search';
export interface IOptions {
placeholder?: string;
width?: number;
@@ -50,7 +51,8 @@ export class PatternInputWidget extends Widget implements IThemable {
constructor(parent: HTMLElement, private contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null),
@IThemeService protected themeService: IThemeService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService protected readonly configurationService: IConfigurationService
) {
super();
this.width = options.width || 100;
@@ -178,6 +180,62 @@ export class PatternInputWidget extends Widget implements IThemable {
}
}
export class IncludePatternInputWidget extends PatternInputWidget {
private _onChangeSearchInEditorsBoxEmitter = this._register(new Emitter<void>());
onChangeSearchInEditorsBox = this._onChangeSearchInEditorsBoxEmitter.event;
constructor(parent: HTMLElement, contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null),
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@IConfigurationService configurationService: IConfigurationService,
) {
super(parent, contextViewProvider, options, themeService, contextKeyService, configurationService);
}
private useSearchInEditorsBox!: Checkbox;
dispose(): void {
super.dispose();
this.useSearchInEditorsBox.dispose();
}
onlySearchInOpenEditors(): boolean {
return this.useSearchInEditorsBox.checked;
}
setOnlySearchInOpenEditors(value: boolean) {
this.useSearchInEditorsBox.checked = value;
}
protected getSubcontrolsWidth(): number {
if (this.configurationService.getValue<ISearchConfiguration>().search?.experimental?.searchInOpenEditors) {
return super.getSubcontrolsWidth() + this.useSearchInEditorsBox.width();
}
return super.getSubcontrolsWidth();
}
protected renderSubcontrols(controlsDiv: HTMLDivElement): void {
this.useSearchInEditorsBox = this._register(new Checkbox({
icon: Codicon.book,
title: nls.localize('onlySearchInOpenEditors', "Search only in Open Editors"),
isChecked: false,
}));
if (!this.configurationService.getValue<ISearchConfiguration>().search?.experimental?.searchInOpenEditors) {
return;
}
this._register(this.useSearchInEditorsBox.onChange(viaKeyboard => {
this._onChangeSearchInEditorsBoxEmitter.fire();
if (!viaKeyboard) {
this.inputBox.focus();
}
}));
this._register(attachCheckboxStyler(this.useSearchInEditorsBox, this.themeService));
controlsDiv.appendChild(this.useSearchInEditorsBox.domNode);
super.renderSubcontrols(controlsDiv);
}
}
export class ExcludePatternInputWidget extends PatternInputWidget {
private _onChangeIgnoreBoxEmitter = this._register(new Emitter<void>());
@@ -185,9 +243,10 @@ export class ExcludePatternInputWidget extends PatternInputWidget {
constructor(parent: HTMLElement, contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null),
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IConfigurationService configurationService: IConfigurationService,
) {
super(parent, contextViewProvider, options, themeService, contextKeyService);
super(parent, contextViewProvider, options, themeService, contextKeyService, configurationService);
}
private useExcludesAndIgnoreFilesBox!: Checkbox;
@@ -24,6 +24,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService, WorkbenchListFocusContextKey, WorkbenchObjectTree } from 'vs/platform/list/browser/listService';
import product from 'vs/platform/product/common/product';
import { Extensions as QuickAccessExtensions, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -998,6 +999,11 @@ configurationRegistry.registerConfiguration({
],
'description': nls.localize('search.sortOrder', "Controls sorting order of search results.")
},
'search.experimental.searchInOpenEditors': {
type: 'boolean',
default: product.quality !== 'stable',
markdownDescription: nls.localize('search.experimental.searchInOpenEditors', "Experimental. When enabled, an option is provided to make workspace search only search files that have been opened. **Requires restart to take effect.**")
}
}
});
@@ -54,7 +54,7 @@ import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/vie
import { IEditorPane } from 'vs/workbench/common/editor';
import { Memento, MementoObject } from 'vs/workbench/common/memento';
import { IViewDescriptorService } from 'vs/workbench/common/views';
import { ExcludePatternInputWidget, PatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget';
import { ExcludePatternInputWidget, IncludePatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget';
import { appendKeyBindingLabel, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions';
import { searchDetailsIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { FileMatchRenderer, FolderMatchRenderer, MatchRenderer, SearchAccessibilityProvider, SearchDelegate, SearchDND } from 'vs/workbench/contrib/search/browser/searchResultsView';
@@ -125,7 +125,7 @@ export class SearchView extends ViewPane {
private queryDetails!: HTMLElement;
private toggleQueryDetailsButton!: HTMLElement;
private inputPatternExcludes!: ExcludePatternInputWidget;
private inputPatternIncludes!: PatternInputWidget;
private inputPatternIncludes!: IncludePatternInputWidget;
private resultsElement!: HTMLElement;
private currentSelectedFileMatch: FileMatch | undefined;
@@ -309,14 +309,17 @@ export class SearchView extends ViewPane {
const filesToIncludeTitle = nls.localize('searchScope.includes', "files to include");
dom.append(folderIncludesList, $('h4', undefined, filesToIncludeTitle));
this.inputPatternIncludes = this._register(this.instantiationService.createInstance(PatternInputWidget, folderIncludesList, this.contextViewService, {
this.inputPatternIncludes = this._register(this.instantiationService.createInstance(IncludePatternInputWidget, folderIncludesList, this.contextViewService, {
ariaLabel: nls.localize('label.includes', 'Search Include Patterns'),
history: patternIncludesHistory,
}));
this.inputPatternIncludes.setValue(patternIncludes);
this._register(this.inputPatternIncludes.onSubmit(triggeredOnType => this.triggerQueryChange({ triggeredOnType, delay: this.searchConfig.searchOnTypeDebouncePeriod })));
this._register(this.inputPatternIncludes.onCancel(() => this.cancelSearch(false)));
this._register(this.inputPatternIncludes.onChangeSearchInEditorsBox(() => this.triggerQueryChange()));
this.trackInputBox(this.inputPatternIncludes.inputFocusTracker, this.inputPatternIncludesFocused);
// excludes list
@@ -385,7 +388,7 @@ export class SearchView extends ViewPane {
return this.searchWidget;
}
get searchIncludePattern(): PatternInputWidget {
get searchIncludePattern(): IncludePatternInputWidget {
return this.inputPatternIncludes;
}
@@ -1293,6 +1296,7 @@ export class SearchView extends ViewPane {
const excludePatternText = this.inputPatternExcludes.getValue().trim();
const includePatternText = this.inputPatternIncludes.getValue().trim();
const useExcludesAndIgnoreFiles = this.inputPatternExcludes.useExcludesAndIgnoreFiles();
const onlySearchInOpenEditors = this.inputPatternIncludes.onlySearchInOpenEditors();
if (contentPattern.length === 0) {
this.clearSearchResults(false);
@@ -1321,6 +1325,7 @@ export class SearchView extends ViewPane {
maxResults: SearchView.MAX_TEXT_RESULTS,
disregardIgnoreFiles: !useExcludesAndIgnoreFiles || undefined,
disregardExcludeSettings: !useExcludesAndIgnoreFiles || undefined,
onlyOpenEditors: onlySearchInOpenEditors,
excludePattern,
includePattern,
previewOptions: {
@@ -1443,14 +1448,26 @@ export class SearchView extends ViewPane {
if (!completed) {
message = SEARCH_CANCELLED_MESSAGE;
} else if (hasIncludes && hasExcludes) {
message = nls.localize('noResultsIncludesExcludes', "No results found in '{0}' excluding '{1}' - ", includePatternText, excludePatternText);
} else if (hasIncludes) {
message = nls.localize('noResultsIncludes', "No results found in '{0}' - ", includePatternText);
} else if (hasExcludes) {
message = nls.localize('noResultsExcludes', "No results found excluding '{0}' - ", excludePatternText);
} else if (this.inputPatternIncludes.onlySearchInOpenEditors()) {
if (hasIncludes && hasExcludes) {
message = nls.localize('noOpenEditorResultsIncludesExcludes', "No results found in open editors matching '{0}' excluding '{1}' - ", includePatternText, excludePatternText);
} else if (hasIncludes) {
message = nls.localize('noOpenEditorResultsIncludes', "No results found in open editors matching '{0}' - ", includePatternText);
} else if (hasExcludes) {
message = nls.localize('noOpenEditorResultsExcludes', "No results found in open editors excluding '{0}' - ", excludePatternText);
} else {
message = nls.localize('noOpenEditorResultsFound', "No results found in open editors. Review your settings for configured exclusions and check your gitignore files - ");
}
} else {
message = nls.localize('noResultsFound', "No results found. Review your settings for configured exclusions and check your gitignore files - ");
if (hasIncludes && hasExcludes) {
message = nls.localize('noResultsIncludesExcludes', "No results found in '{0}' excluding '{1}' - ", includePatternText, excludePatternText);
} else if (hasIncludes) {
message = nls.localize('noResultsIncludes', "No results found in '{0}' - ", includePatternText);
} else if (hasExcludes) {
message = nls.localize('noResultsExcludes', "No results found excluding '{0}' - ", excludePatternText);
} else {
message = nls.localize('noResultsFound', "No results found. Review your settings for configured exclusions and check your gitignore files - ");
}
}
// Indicate as status to ARIA
@@ -1472,6 +1489,7 @@ export class SearchView extends ViewPane {
this.inputPatternExcludes.setValue('');
this.inputPatternIncludes.setValue('');
this.inputPatternIncludes.setOnlySearchInOpenEditors(false);
this.triggerQueryChange({ preserveFocus: false });
}));
@@ -1599,7 +1617,7 @@ export class SearchView extends ViewPane {
this.messageDisposables.push(dom.addDisposableListener(openInEditorLink, dom.EventType.CLICK, (e: MouseEvent) => {
dom.EventHelper.stop(e, false);
this.instantiationService.invokeFunction(createEditorFromSearchResult, this.searchResult, this.searchIncludePattern.getValue(), this.searchExcludePattern.getValue());
this.instantiationService.invokeFunction(createEditorFromSearchResult, this.searchResult, this.searchIncludePattern.getValue(), this.searchExcludePattern.getValue(), this.searchIncludePattern.onlySearchInOpenEditors());
}));
this.reLayout();
@@ -16,6 +16,7 @@ import { isMultilineRegexSource } from 'vs/editor/common/model/textModelSearch';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceContextService, IWorkspaceFolderData, toWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { getExcludes, ICommonQueryProps, IFileQuery, IFolderQuery, IPatternInfo, ISearchConfiguration, ITextQuery, ITextSearchPreviewOptions, pathIncludedInQuery, QueryType } from 'vs/workbench/services/search/common/search';
@@ -59,6 +60,7 @@ export interface ICommonQueryBuilderOptions {
disregardExcludeSettings?: boolean;
disregardSearchExcludeSettings?: boolean;
ignoreSymlinks?: boolean;
onlyOpenEditors?: boolean;
}
export interface IFileQueryBuilderOptions extends ICommonQueryBuilderOptions {
@@ -81,6 +83,7 @@ export class QueryBuilder {
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService,
@IPathService private readonly pathService: IPathService
) {
}
@@ -148,20 +151,21 @@ export class QueryBuilder {
};
}
private handleIncludeExclude(pattern: string | string[] | undefined, expandPatterns: boolean | undefined): ISearchPathsInfo {
private handleIncludeExclude(pattern: string | string[] | undefined, expandPatterns: 'strict' | 'loose' | 'none'): ISearchPathsInfo {
if (!pattern) {
return {};
}
pattern = Array.isArray(pattern) ? pattern.map(normalizeSlashes) : normalizeSlashes(pattern);
return expandPatterns ?
this.parseSearchPaths(pattern) :
{ pattern: patternListToIExpression(...(Array.isArray(pattern) ? pattern : [pattern])) };
return expandPatterns === 'none' ?
{ pattern: patternListToIExpression(...(Array.isArray(pattern) ? pattern : [pattern])) } :
this.parseSearchPaths(pattern, expandPatterns === 'strict');
}
private commonQuery(folderResources: (IWorkspaceFolderData | URI)[] = [], options: ICommonQueryBuilderOptions = {}): ICommonQueryProps<uri> {
const includeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.includePattern, options.expandPatterns);
const excludeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.excludePattern, options.expandPatterns);
private commonQuery(folderResources: (IWorkspaceFolderData | URI)[] = [], options: ICommonQueryBuilderOptions = {}, strictPatterns?: boolean): ICommonQueryProps<uri> {
const patternExpansionMode = strictPatterns ? 'strict' : options.expandPatterns ? 'loose' : 'none';
const includeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.includePattern, patternExpansionMode);
const excludeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.excludePattern, patternExpansionMode);
// Build folderQueries from searchPaths, if given, otherwise folderResources
const includeFolderName = folderResources.length > 1;
@@ -178,9 +182,35 @@ export class QueryBuilder {
excludePattern: excludeSearchPathsInfo.pattern,
includePattern: includeSearchPathsInfo.pattern,
onlyOpenEditors: options.onlyOpenEditors,
maxResults: options.maxResults
};
// When "onlyOpenEditors" is enabled, filter all opened editors by the existing include/exclude patterns,
// then rerun the query build setting the includes to those remaining editors
if (options.onlyOpenEditors) {
const openEditors = arrays.coalesce(arrays.flatten(this.editorGroupsService.groups.map(group => group.editors.map(editor => editor.resource))));
const openEditorsInQuery = openEditors.filter(editor => pathIncludedInQuery(queryProps, editor.fsPath));
const openEditorIncludes = openEditorsInQuery.map(editor => {
const workspace = this.workspaceContextService.getWorkspaceFolder(editor);
if (workspace) {
const relPath = path.relative(workspace?.uri.fsPath, editor.fsPath);
return includeFolderName ? `./${workspace.name}/${relPath}` : `${relPath}`;
}
else {
return editor.fsPath.replace(/^\//, '');
}
});
return this.commonQuery(folderResources, {
...options,
onlyOpenEditors: false,
includePattern: openEditorIncludes,
excludePattern: openEditorIncludes.length
? options.excludePattern
: '**/*' // when there are no included editors, explicitly exclude all other files
}, true);
}
// Filter extraFileResources against global include/exclude patterns - they are already expected to not belong to a workspace
const extraFileResources = options.extraFileResources && options.extraFileResources.filter(extraFile => pathIncludedInQuery(queryProps, extraFile.fsPath));
queryProps.extraFileResources = extraFileResources && extraFileResources.length ? extraFileResources : undefined;
@@ -224,11 +254,11 @@ export class QueryBuilder {
/**
* Take the includePattern as seen in the search viewlet, and split into components that look like searchPaths, and
* glob patterns. Glob patterns are expanded from 'foo/bar' to '{foo/bar/**, **\/foo/bar}.
* glob patterns. When `strictPatterns` is false, patterns are expanded from 'foo/bar' to '{foo/bar/**, **\/foo/bar}.
*
* Public for test.
*/
parseSearchPaths(pattern: string | string[]): ISearchPathsInfo {
parseSearchPaths(pattern: string | string[], strictPatterns = false): ISearchPathsInfo {
const isSearchPath = (segment: string) => {
// A segment is a search path if it is an absolute path or starts with ./, ../, .\, or ..\
return path.isAbsolute(segment) || /^\.\.?([\/\\]|$)/.test(segment);
@@ -251,15 +281,15 @@ export class QueryBuilder {
.map(s => strings.rtrim(s, '/'))
.map(s => strings.rtrim(s, '\\'))
.map(p => {
if (p[0] === '.') {
if (!strictPatterns && p[0] === '.') {
p = '*' + p; // convert ".js" to "*.js"
}
return expandGlobalGlob(p);
return strictPatterns ? [p] : expandGlobalGlob(p);
});
const result: ISearchPathsInfo = {};
const searchPaths = this.expandSearchPathPatterns(groups.searchPaths || []);
const searchPaths = this.expandSearchPathPatterns(groups.searchPaths || [], strictPatterns);
if (searchPaths && searchPaths.length) {
result.searchPaths = searchPaths;
}
@@ -282,7 +312,7 @@ export class QueryBuilder {
/**
* Split search paths (./ or ../ or absolute paths in the includePatterns) into absolute paths and globs applied to those paths
*/
private expandSearchPathPatterns(searchPaths: string[]): ISearchPathPattern[] {
private expandSearchPathPatterns(searchPaths: string[], strictPatterns: boolean): ISearchPathPattern[] {
if (!searchPaths || !searchPaths.length) {
// No workspace => ignore search paths
return [];
@@ -302,7 +332,7 @@ export class QueryBuilder {
// Expanded search paths to multiple resolved patterns (with ** and without)
return arrays.flatten(
oneExpanded.map(oneExpandedResult => this.resolveOneSearchPathPattern(oneExpandedResult, globPortion)));
oneExpanded.map(oneExpandedResult => this.resolveOneSearchPathPattern(oneExpandedResult, globPortion, strictPatterns)));
}));
const searchPathPatternMap = new Map<string, ISearchPathPattern>();
@@ -388,7 +418,7 @@ export class QueryBuilder {
return [];
}
private resolveOneSearchPathPattern(oneExpandedResult: IOneSearchPathPattern, globPortion?: string): IOneSearchPathPattern[] {
private resolveOneSearchPathPattern(oneExpandedResult: IOneSearchPathPattern, globPortion: string | undefined, strictPatterns: boolean): IOneSearchPathPattern[] {
const pattern = oneExpandedResult.pattern && globPortion ?
`${oneExpandedResult.pattern}/${globPortion}` :
oneExpandedResult.pattern || globPortion;
@@ -399,7 +429,7 @@ export class QueryBuilder {
pattern
}];
if (pattern && !pattern.endsWith('**')) {
if (!strictPatterns && pattern && !pattern.endsWith('**')) {
results.push({
searchPath: oneExpandedResult.searchPath,
pattern: pattern + '/**'
@@ -571,15 +571,42 @@ suite('QueryBuilder', () => {
].forEach(([includePattern, expectedPatterns]) => testSimpleIncludes(<string>includePattern, <string[]>expectedPatterns));
});
function testIncludes(includePattern: string, expectedResult: ISearchPathsInfo): void {
test('strict includes', () => {
function testSimpleIncludes(includePattern: string, expectedPatterns: string[]): void {
assert.deepEqual(
queryBuilder.parseSearchPaths(includePattern, true),
{
pattern: patternsToIExpression(...expectedPatterns)
},
includePattern);
}
[
['a', ['a']],
['a/b', ['a/b']],
['a/b, c', ['a/b', 'c']],
['a,.txt', ['a', '.txt']],
['a,,,b', ['a', 'b']],
['**/a,b/**', ['**/a', 'b/**']]
].forEach(([includePattern, expectedPatterns]) => testSimpleIncludes(<string>includePattern, <string[]>expectedPatterns));
});
function testIncludes(includePattern: string, expectedResultLoose: ISearchPathsInfo, expectedResultStrict?: ISearchPathsInfo): void {
assertEqualSearchPathResults(
queryBuilder.parseSearchPaths(includePattern),
expectedResult,
expectedResultLoose,
includePattern);
if (expectedResultStrict) {
assertEqualSearchPathResults(
queryBuilder.parseSearchPaths(includePattern, true),
expectedResultStrict,
includePattern);
}
}
function testIncludesDataItem([includePattern, expectedResult]: [string, ISearchPathsInfo]): void {
testIncludes(includePattern, expectedResult);
function testIncludesDataItem([includePattern, expectedResultLoose, expectedResultStrict]: [string, ISearchPathsInfo, ISearchPathsInfo] | [string, ISearchPathsInfo]): void {
testIncludes(includePattern, expectedResultLoose, expectedResultStrict);
}
test('absolute includes', () => {
@@ -652,7 +679,7 @@ suite('QueryBuilder', () => {
});
test('relative includes w/single root folder', () => {
const cases: [string, ISearchPathsInfo][] = [
const cases: ([string, ISearchPathsInfo] | [string, ISearchPathsInfo, ISearchPathsInfo])[] = [
[
'./a',
{
@@ -660,6 +687,12 @@ suite('QueryBuilder', () => {
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a', 'a/**')
}]
},
{
searchPaths: [{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a')
}]
}
],
[
@@ -669,6 +702,12 @@ suite('QueryBuilder', () => {
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a', 'a/**')
}]
},
{
searchPaths: [{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a')
}]
}
],
[
@@ -700,6 +739,12 @@ suite('QueryBuilder', () => {
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a/b', 'a/b/**', 'c/d', 'c/d/**')
}]
},
{
searchPaths: [{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a/b', 'c/d',)
}]
}
],
[
@@ -735,9 +780,14 @@ suite('QueryBuilder', () => {
mockWorkspace.folders = toWorkspaceFolders([{ path: ROOT_1_URI.fsPath }, { path: getUri(ROOT_2).fsPath }], WS_CONFIG_PATH, extUriBiasedIgnorePathCase);
mockWorkspace.configuration = uri.file(fixPath('config'));
const cases: [string, ISearchPathsInfo][] = [
const cases: ([string, ISearchPathsInfo] | [string, ISearchPathsInfo, ISearchPathsInfo])[] = [
[
'./root1',
{
searchPaths: [{
searchPath: getUri(ROOT_1)
}]
},
{
searchPaths: [{
searchPath: getUri(ROOT_1)
@@ -750,6 +800,36 @@ suite('QueryBuilder', () => {
searchPaths: [{
searchPath: getUri(ROOT_2),
}]
},
{
searchPaths: [{
searchPath: getUri(ROOT_2),
}]
}
],
[
'./root1/a/b, ./root2/a.txt',
{
searchPaths: [
{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a/b', 'a/b/**')
},
{
searchPath: getUri(ROOT_2),
pattern: patternsToIExpression('a.txt', 'a.txt/**')
}]
},
{
searchPaths: [
{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('a/b')
},
{
searchPath: getUri(ROOT_2),
pattern: patternsToIExpression('a.txt')
}]
}
],
[
@@ -776,7 +856,7 @@ suite('QueryBuilder', () => {
mockWorkspace.folders = toWorkspaceFolders([{ path: ROOT_1_URI.fsPath, name: ROOT_1_FOLDERNAME }, { path: getUri(ROOT_2).fsPath }], WS_CONFIG_PATH, extUriBiasedIgnorePathCase);
mockWorkspace.configuration = uri.file(fixPath('config'));
const cases: [string, ISearchPathsInfo][] = [
const cases: ([string, ISearchPathsInfo] | [string, ISearchPathsInfo, ISearchPathsInfo])[] = [
[
'./foldername',
{
@@ -792,6 +872,12 @@ suite('QueryBuilder', () => {
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('foo', 'foo/**')
}]
},
{
searchPaths: [{
searchPath: ROOT_1_URI,
pattern: patternsToIExpression('foo', 'foo')
}]
}
]
];
@@ -804,7 +890,7 @@ suite('QueryBuilder', () => {
mockWorkspace.folders = toWorkspaceFolders([{ path: ROOT_1_URI.fsPath }, { path: getUri(ROOT_2).fsPath }, { path: getUri(ROOT_3).fsPath }], WS_CONFIG_PATH, extUriBiasedIgnorePathCase);
mockWorkspace.configuration = uri.file(fixPath('/config'));
const cases: [string, ISearchPathsInfo][] = [
const cases: ([string, ISearchPathsInfo] | [string, ISearchPathsInfo, ISearchPathsInfo])[] = [
[
'',
{
@@ -819,6 +905,11 @@ suite('QueryBuilder', () => {
],
[
'./root1',
{
searchPaths: [{
searchPath: getUri(ROOT_1)
}]
},
{
searchPaths: [{
searchPath: getUri(ROOT_1)
@@ -318,7 +318,7 @@ registerAction2(class extends Action2 {
const instantiationService = accessor.get(IInstantiationService);
const searchView = getSearchView(viewsService);
if (searchView) {
await instantiationService.invokeFunction(createEditorFromSearchResult, searchView.searchResult, searchView.searchIncludePattern.getValue(), searchView.searchExcludePattern.getValue());
await instantiationService.invokeFunction(createEditorFromSearchResult, searchView.searchResult, searchView.searchIncludePattern.getValue(), searchView.searchExcludePattern.getValue(), searchView.searchIncludePattern.onlySearchInOpenEditors());
}
}
});
@@ -38,7 +38,7 @@ import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platfor
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor';
import { ExcludePatternInputWidget, PatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget';
import { ExcludePatternInputWidget, IncludePatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget';
import { SearchWidget } from 'vs/workbench/contrib/search/browser/searchWidget';
import { InputBoxFocusedKey } from 'vs/workbench/contrib/search/common/constants';
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
@@ -67,7 +67,7 @@ export class SearchEditor extends BaseTextEditor {
private searchResultEditor!: CodeEditorWidget;
private queryEditorContainer!: HTMLElement;
private dimension?: DOM.Dimension;
private inputPatternIncludes!: PatternInputWidget;
private inputPatternIncludes!: IncludePatternInputWidget;
private inputPatternExcludes!: ExcludePatternInputWidget;
private includesExcludesContainer!: HTMLElement;
private toggleQueryDetailsButton!: HTMLElement;
@@ -168,10 +168,11 @@ export class SearchEditor extends BaseTextEditor {
const folderIncludesList = DOM.append(this.includesExcludesContainer, DOM.$('.file-types.includes'));
const filesToIncludeTitle = localize('searchScope.includes', "files to include");
DOM.append(folderIncludesList, DOM.$('h4', undefined, filesToIncludeTitle));
this.inputPatternIncludes = this._register(this.instantiationService.createInstance(PatternInputWidget, folderIncludesList, this.contextViewService, {
this.inputPatternIncludes = this._register(this.instantiationService.createInstance(IncludePatternInputWidget, folderIncludesList, this.contextViewService, {
ariaLabel: localize('label.includes', 'Search Include Patterns'),
}));
this.inputPatternIncludes.onSubmit(triggeredOnType => this.triggerSearch({ resetCursor: false, delay: triggeredOnType ? this.searchConfig.searchOnTypeDebouncePeriod : 0 }));
this._register(this.inputPatternIncludes.onChangeSearchInEditorsBox(() => this.triggerSearch()));
// // Excludes
const excludesList = DOM.append(this.includesExcludesContainer, DOM.$('.file-types.excludes'));
@@ -181,7 +182,7 @@ export class SearchEditor extends BaseTextEditor {
ariaLabel: localize('label.excludes', 'Search Exclude Patterns'),
}));
this.inputPatternExcludes.onSubmit(triggeredOnType => this.triggerSearch({ resetCursor: false, delay: triggeredOnType ? this.searchConfig.searchOnTypeDebouncePeriod : 0 }));
this.inputPatternExcludes.onChangeIgnoreBox(() => this.triggerSearch());
this._register(this.inputPatternExcludes.onChangeIgnoreBox(() => this.triggerSearch()));
[this.queryEditorWidget.searchInput, this.inputPatternIncludes, this.inputPatternExcludes].map(input =>
this._register(attachInputBoxStyler(input, this.themeService, { inputBorder: searchEditorTextInputBorder })));
@@ -449,6 +450,7 @@ export class SearchEditor extends BaseTextEditor {
isRegexp: this.queryEditorWidget.searchInput.getRegex(),
matchWholeWord: this.queryEditorWidget.searchInput.getWholeWords(),
useExcludeSettingsAndIgnoreFiles: this.inputPatternExcludes.useExcludesAndIgnoreFiles(),
onlyOpenEditors: this.inputPatternIncludes.onlySearchInOpenEditors(),
showIncludesExcludes: this.showingIncludesExcludes
};
}
@@ -483,6 +485,7 @@ export class SearchEditor extends BaseTextEditor {
disregardExcludeSettings: !config.useExcludeSettingsAndIgnoreFiles || undefined,
excludePattern: config.filesToExclude,
includePattern: config.filesToInclude,
onlyOpenEditors: config.onlyOpenEditors,
previewOptions: {
matchLines: 1,
charsPerLine: 1000
@@ -575,6 +578,7 @@ export class SearchEditor extends BaseTextEditor {
if (config.contextLines !== undefined) { this.queryEditorWidget.setContextLines(config.contextLines); }
if (config.filesToExclude !== undefined) { this.inputPatternExcludes.setValue(config.filesToExclude); }
if (config.filesToInclude !== undefined) { this.inputPatternIncludes.setValue(config.filesToInclude); }
if (config.onlyOpenEditors !== undefined) { this.inputPatternIncludes.setOnlySearchInOpenEditors(config.onlyOpenEditors); }
if (config.useExcludeSettingsAndIgnoreFiles !== undefined) { this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(config.useExcludeSettingsAndIgnoreFiles); }
if (config.showIncludesExcludes !== undefined) { this.toggleIncludesExcludes(config.showIncludesExcludes); }
}
@@ -82,6 +82,7 @@ export async function openSearchEditor(accessor: ServicesAccessor): Promise<void
if (searchView) {
await instantiationService.invokeFunction(openNewSearchEditor, {
filesToInclude: searchView.searchIncludePattern.getValue(),
onlyOpenEditors: searchView.searchIncludePattern.onlySearchInOpenEditors(),
filesToExclude: searchView.searchExcludePattern.getValue(),
isRegexp: searchView.searchAndReplaceWidget.searchInput.getRegex(),
isCaseSensitive: searchView.searchAndReplaceWidget.searchInput.getCaseSensitive(),
@@ -161,7 +162,7 @@ export const openNewSearchEditor =
};
export const createEditorFromSearchResult =
async (accessor: ServicesAccessor, searchResult: SearchResult, rawIncludePattern: string, rawExcludePattern: string) => {
async (accessor: ServicesAccessor, searchResult: SearchResult, rawIncludePattern: string, rawExcludePattern: string, onlySearchInOpenEditors: boolean) => {
if (!searchResult.query) {
console.error('Expected searchResult.query to be defined. Got', searchResult);
return;
@@ -180,6 +181,7 @@ export const createEditorFromSearchResult =
const labelFormatter = (uri: URI): string => labelService.getUriLabel(uri, { relative: true });
const { text, matchRanges, config } = serializeSearchResultForEditor(searchResult, rawIncludePattern, rawExcludePattern, 0, labelFormatter, sortOrder);
config.onlyOpenEditors = onlySearchInOpenEditors;
const contextLines = configurationService.getValue<ISearchConfigurationProperties>('search').searchEditor.defaultNumberOfContextLines;
if (searchResult.isDirty || contextLines === 0 || contextLines === null) {
@@ -40,6 +40,7 @@ export type SearchConfiguration = {
isRegexp: boolean,
useExcludeSettingsAndIgnoreFiles: boolean,
showIncludesExcludes: boolean,
onlyOpenEditors: boolean,
};
export const SEARCH_EDITOR_EXT = '.code-search';
@@ -115,6 +115,7 @@ const contentPatternToSearchConfiguration = (pattern: ITextQuery, includes: stri
showIncludesExcludes: !!(includes || excludes || pattern?.userDisabledExcludesAndIgnoreFiles),
useExcludeSettingsAndIgnoreFiles: (pattern?.userDisabledExcludesAndIgnoreFiles === undefined ? true : !pattern.userDisabledExcludesAndIgnoreFiles),
contextLines,
onlyOpenEditors: !!pattern.onlyOpenEditors,
};
};
@@ -131,6 +132,7 @@ export const serializeSearchConfiguration = (config: Partial<SearchConfiguration
config.isCaseSensitive && 'CaseSensitive',
config.matchWholeWord && 'WordMatch',
config.isRegexp && 'RegExp',
config.onlyOpenEditors && 'OpenEditors',
(config.useExcludeSettingsAndIgnoreFiles === false) && 'IgnoreExcludeSettings'
]).join(' ')}`,
config.filesToInclude ? `# Including: ${config.filesToInclude}` : undefined,
@@ -153,6 +155,7 @@ export const defaultSearchConfig = (): SearchConfiguration => ({
matchWholeWord: false,
contextLines: 0,
showIncludesExcludes: false,
onlyOpenEditors: false,
});
export const extractSearchQueryFromLines = (lines: string[]): SearchConfiguration => {
@@ -197,6 +200,7 @@ export const extractSearchQueryFromLines = (lines: string[]): SearchConfiguratio
query.isCaseSensitive = value.indexOf('CaseSensitive') !== -1;
query.useExcludeSettingsAndIgnoreFiles = value.indexOf('IgnoreExcludeSettings') === -1;
query.matchWholeWord = value.indexOf('WordMatch') !== -1;
query.onlyOpenEditors = value.indexOf('OpenEditors') !== -1;
}
}
}
@@ -6,7 +6,7 @@
import { Action, IAction } from 'vs/base/common/actions';
import { EndOfLinePreference } from 'vs/editor/common/model';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { TERMINAL_VIEW_ID, ITerminalConfigHelper, TitleEventSource, TERMINAL_COMMAND_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, IRemoteTerminalAttachTarget } from 'vs/workbench/contrib/terminal/common/terminal';
import { TERMINAL_VIEW_ID, ITerminalConfigHelper, TitleEventSource, TERMINAL_COMMAND_ID, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, TERMINAL_ACTION_CATEGORY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, IRemoteTerminalAttachTarget, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE } from 'vs/workbench/contrib/terminal/common/terminal';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -750,7 +750,7 @@ export function registerTerminalActions() {
keybinding: {
primary: KeyMod.Shift | KeyCode.PageDown,
mac: { primary: KeyCode.PageDown },
when: KEYBINDING_CONTEXT_TERMINAL_FOCUS,
when: ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.negate()),
weight: KeybindingWeight.WorkbenchContrib
},
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
@@ -810,7 +810,7 @@ export function registerTerminalActions() {
keybinding: {
primary: KeyMod.Shift | KeyCode.PageUp,
mac: { primary: KeyCode.PageUp },
when: KEYBINDING_CONTEXT_TERMINAL_FOCUS,
when: ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.negate()),
weight: KeybindingWeight.WorkbenchContrib
},
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
@@ -1416,7 +1416,7 @@ export function registerTerminalActions() {
{
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F,
when: ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED),
weight: KeybindingWeight.WorkbenchContrib
weight: KeybindingWeight.WorkbenchContrib + 50
}
],
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
@@ -25,7 +25,7 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, TERMINAL_CREATION_COMMANDS } from 'vs/workbench/contrib/terminal/common/terminal';
import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, TERMINAL_CREATION_COMMANDS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE } from 'vs/workbench/contrib/terminal/common/terminal';
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
@@ -184,6 +184,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
public constructor(
private readonly _terminalFocusContextKey: IContextKey<boolean>,
private readonly _terminalShellTypeContextKey: IContextKey<string>,
private readonly _terminalAltBufferActiveContextKey: IContextKey<boolean>,
private readonly _configHelper: TerminalConfigHelper,
private _container: HTMLElement | undefined,
private _shellLaunchConfig: IShellLaunchConfig,
@@ -219,6 +220,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._terminalHasTextContextKey = KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED.bindTo(this._contextKeyService);
this._terminalA11yTreeFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS.bindTo(this._contextKeyService);
this._terminalAltBufferActiveContextKey = KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.bindTo(this._contextKeyService);
this.disableLayout = false;
this._logService.trace(`terminalInstance#ctor (id: ${this.id})`, this._shellLaunchConfig);
@@ -396,7 +398,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
const editorOptions = this._configurationService.getValue<IEditorOptions>('editor');
const xterm = new Terminal({
altClickMovesCursor: config.altClickMovesCursor,
altClickMovesCursor: config.altClickMovesCursor && editorOptions.multiCursorModifier === 'alt',
scrollback: config.scrollback,
theme: this._getXtermTheme(),
drawBoldTextInBrightColors: config.drawBoldTextInBrightColors,
@@ -431,6 +433,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._xterm.onLineFeed(() => this._onLineFeed());
this._xterm.onKey(e => this._onKey(e.key, e.domEvent));
this._xterm.onSelectionChange(async () => this._onSelectionChange());
this._xterm.buffer.onBufferChange(() => this._refreshAltBufferContextKey());
this._processManager.onProcessData(e => this._onProcessData(e));
this._xterm.onData(data => this._processManager.write(data));
@@ -774,6 +777,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this.notifyFindWidgetFocusChanged(false);
}
private _refreshAltBufferContextKey() {
this._terminalAltBufferActiveContextKey.set(!!(this._xterm && this._xterm.buffer.active === this._xterm.buffer.alternate));
}
public dispose(immediate?: boolean): void {
this._logService.trace(`terminalInstance#dispose (id: ${this.id})`);
@@ -828,6 +835,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
public focus(force?: boolean): void {
this._refreshAltBufferContextKey();
if (!this._xterm) {
return;
}
@@ -157,11 +157,12 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
const userHomeUri = await this._pathService.userHome();
this.userHome = userHomeUri.path;
if (hasRemoteAuthority) {
const remoteEnv = await this._remoteAgentService.getEnvironment();
if (remoteEnv) {
this.userHome = remoteEnv.userHome.path;
this.os = remoteEnv.os;
}
this._remoteAgentService.getEnvironment().then(remoteEnv => {
if (remoteEnv) {
this.userHome = remoteEnv.userHome.path;
this.os = remoteEnv.os;
}
});
}
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot();
@@ -24,7 +24,7 @@ import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/term
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab';
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
import { IAvailableShellsRequest, IRemoteTerminalAttachTarget, IShellDefinition, IShellLaunchConfig, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalLaunchError, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, ITerminalsLayoutInfoById, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, LinuxDistro, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
import { IAvailableShellsRequest, IRemoteTerminalAttachTarget, IShellDefinition, IShellLaunchConfig, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalLaunchError, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, ITerminalsLayoutInfoById, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, LinuxDistro, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -43,6 +43,7 @@ export class TerminalService implements ITerminalService {
private _isShuttingDown: boolean;
private _terminalFocusContextKey: IContextKey<boolean>;
private _terminalShellTypeContextKey: IContextKey<string>;
private _terminalAltBufferActiveContextKey: IContextKey<boolean>;
private _findWidgetVisible: IContextKey<boolean>;
private _terminalTabs: ITerminalTab[] = [];
private _backgroundedTerminalInstances: ITerminalInstance[] = [];
@@ -126,6 +127,7 @@ export class TerminalService implements ITerminalService {
lifecycleService.onShutdown(() => this._onShutdown());
this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService);
this._terminalShellTypeContextKey = KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE.bindTo(this._contextKeyService);
this._terminalAltBufferActiveContextKey = KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.bindTo(this._contextKeyService);
this._findWidgetVisible = KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE.bindTo(this._contextKeyService);
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper);
this.onTabDisposed(tab => this._removeTab(tab));
@@ -718,7 +720,14 @@ export class TerminalService implements ITerminalService {
public createInstance(container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance {
const instance = this._instantiationService.createInstance(TerminalInstance, this._terminalFocusContextKey, this._terminalShellTypeContextKey, this._configHelper, container, shellLaunchConfig);
const instance = this._instantiationService.createInstance(TerminalInstance,
this._terminalFocusContextKey,
this._terminalShellTypeContextKey,
this._terminalAltBufferActiveContextKey,
this._configHelper,
container,
shellLaunchConfig
);
this._onInstanceCreated.fire(instance);
return instance;
}
@@ -24,6 +24,8 @@ export const KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY = 'terminalShellType';
/** A context key that is set to the detected shell for the most recently active terminal, this is set to the last known value when no terminals exist. */
export const KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE = new RawContextKey<string>(KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY, undefined);
export const KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE = new RawContextKey<boolean>('terminalAltBufferActive', false);
/** A context key that is set when the integrated terminal does not have focus. */
export const KEYBINDING_CONTEXT_TERMINAL_NOT_FOCUSED = KEYBINDING_CONTEXT_TERMINAL_FOCUS.toNegated();
@@ -91,7 +91,7 @@ export const terminalConfiguration: IConfigurationNode = {
default: false
},
'terminal.integrated.altClickMovesCursor': {
description: localize('terminal.integrated.altClickMovesCursor', "If enabled, alt/option + click will move the prompt cursor to position underneath the mouse. This may not work reliably depending on your shell."),
description: localize('terminal.integrated.altClickMovesCursor', "If enabled, alt/option + click will reposition the prompt cursor to underneath the mouse when `#editor.multiCursorModifier#` is set to `'alt'` (the default value). This may not work reliably depending on your shell."),
type: 'boolean',
default: true
},
@@ -111,54 +111,59 @@ export async function openEditorWith(
return picked.item.handler.open(input, openOptions, targetGroup, OpenEditorContext.NEW_EDITOR)?.override;
}
const picked = await new Promise<PickedResult | undefined>(resolve => {
picker.onDidAccept(e => {
if (picker.selectedItems.length === 1) {
const result: PickedResult = {
item: picker.selectedItems[0],
keyMods: picker.keyMods,
openInBackground: e.inBackground
};
let picked: PickedResult | undefined;
try {
picked = await new Promise<PickedResult | undefined>(resolve => {
picker.onDidAccept(e => {
if (picker.selectedItems.length === 1) {
const result: PickedResult = {
item: picker.selectedItems[0],
keyMods: picker.keyMods,
openInBackground: e.inBackground
};
if (e.inBackground) {
openEditor(result);
} else {
resolve(result);
}
} else {
resolve(undefined);
}
});
picker.onDidTriggerItemButton(e => {
const pick = e.item;
const id = pick.id;
resolve({ item: pick, openInBackground: false }); // open the view
picker.dispose();
// And persist the setting
if (pick && id) {
const newAssociation: CustomEditorAssociation = { viewType: id, filenamePattern: '*' + resourceExt };
const currentAssociations = [...configurationService.getValue<CustomEditorsAssociations>(customEditorsAssociationsSettingId)];
// First try updating existing association
for (let i = 0; i < currentAssociations.length; ++i) {
const existing = currentAssociations[i];
if (existing.filenamePattern === newAssociation.filenamePattern) {
currentAssociations.splice(i, 1, newAssociation);
configurationService.updateValue(customEditorsAssociationsSettingId, currentAssociations);
return;
if (e.inBackground) {
openEditor(result);
} else {
resolve(result);
}
} else {
resolve(undefined);
}
});
// Otherwise, create a new one
currentAssociations.unshift(newAssociation);
configurationService.updateValue(customEditorsAssociationsSettingId, currentAssociations);
}
picker.onDidTriggerItemButton(e => {
const pick = e.item;
const id = pick.id;
resolve({ item: pick, openInBackground: false }); // open the view
picker.dispose();
// And persist the setting
if (pick && id) {
const newAssociation: CustomEditorAssociation = { viewType: id, filenamePattern: '*' + resourceExt };
const currentAssociations = [...configurationService.getValue<CustomEditorsAssociations>(customEditorsAssociationsSettingId)];
// First try updating existing association
for (let i = 0; i < currentAssociations.length; ++i) {
const existing = currentAssociations[i];
if (existing.filenamePattern === newAssociation.filenamePattern) {
currentAssociations.splice(i, 1, newAssociation);
configurationService.updateValue(customEditorsAssociationsSettingId, currentAssociations);
return;
}
}
// Otherwise, create a new one
currentAssociations.unshift(newAssociation);
configurationService.updateValue(customEditorsAssociationsSettingId, currentAssociations);
}
});
picker.show();
});
picker.show();
});
} finally {
picker.dispose();
}
if (!picked) {
return undefined;
@@ -51,10 +51,10 @@ export const content: GettingStartedContent = [
items: [
{
id: 'runProjectTask',
title: localize('gettingStarted.runProject.title', "Build & run your project"),
description: localize('gettingStarted.runProject.description', "Build, run & debug your application in your codespace instead of locally."),
title: localize('gettingStarted.runProject.title', "Build & run your app"),
description: localize('gettingStarted.runProject.description', "Build, run & debug your code right from the browser."),
button: {
title: localize('gettingStarted.runProject.button', "Run Project"),
title: localize('gettingStarted.runProject.button', "Run Code"),
command: 'workbench.action.debug.selectandstart'
},
doneOn: { commandExecuted: 'workbench.action.debug.selectandstart' },
@@ -65,7 +65,7 @@ export const content: GettingStartedContent = [
title: localize('gettingStarted.forwardPorts.title', "Access your running application"),
description: localize('gettingStarted.forwardPorts.description', "Ports running within your codespace are automatically forwarded to the web, so you can open them in your browser."),
button: {
title: localize('gettingStarted.forwardPorts.button', "Show Ports panel"),
title: localize('gettingStarted.forwardPorts.button', "Show Ports Panel"),
command: '~remote.forwardedPorts.focus'
},
doneOn: { commandExecuted: '~remote.forwardedPorts.focus' },
@@ -73,10 +73,10 @@ export const content: GettingStartedContent = [
},
{
id: 'pullRequests',
title: localize('gettingStarted.pullRequests.title', "Pull pequests at your fingertips"),
description: localize('gettingStarted.pullRequests.description', "Codespaces brings your GitHub workflow closer to your code, where you can view pull requests, add comments, merge branches, and more."),
title: localize('gettingStarted.pullRequests.title', "Pull requests at your fingertips"),
description: localize('gettingStarted.pullRequests.description', "Bring your GitHub workflow closer to your code, so you can review pull requests, add comments, merge branches, and more."),
button: {
title: localize('gettingStarted.pullRequests.button', "Open GitHub view"),
title: localize('gettingStarted.pullRequests.button', "Open GitHub View"),
command: 'workbench.view.extension.github-pull-requests'
},
doneOn: { commandExecuted: 'workbench.view.extension.github-pull-requests' },
@@ -85,7 +85,7 @@ export const content: GettingStartedContent = [
{
id: 'remoteTerminal',
title: localize('gettingStarted.remoteTerminal.title', "Run tasks in the integrated terminal"),
description: localize('gettingStarted.remoteTerminal.description', "Access your full development environment in the cloud and perform quick command-line tasks."),
description: localize('gettingStarted.remoteTerminal.description', "Perform quick command-line tasks using the built-in terminal."),
button: {
title: localize('gettingStarted.remoteTerminal.button', "Focus Terminal"),
command: 'terminal.focus'
@@ -96,7 +96,7 @@ export const content: GettingStartedContent = [
{
id: 'openVSC',
title: localize('gettingStarted.openVSC.title', "Develop remotely in VS Code"),
description: localize('gettingStarted.openVSC.description', "Access the power of your cloud development environment from your local VS Code. Set up your local VS Code by installing the GitHub Codespaces extension and connecting your GitHub account."),
description: localize('gettingStarted.openVSC.description', "Access the power of your cloud development environment from your local VS Code. Set it up by installing the GitHub Codespaces extension and connecting your GitHub account."),
button: {
title: localize('gettingStarted.openVSC.button', "Open in VS Code"),
command: 'github.codespaces.openInStable'
@@ -120,15 +120,15 @@ export const content: GettingStartedContent = [
{
id: 'pickColorTheme',
title: localize('gettingStarted.pickColor.title', "Customize the look with themes"),
description: localize('gettingStarted.pickColor.description', "Pick a theme to match your taste and mood. Browse even more from the vibrant themes community."),
button: { title: localize('gettingStarted.pickColor.button', "Pick your Theme"), command: 'workbench.action.selectTheme' },
description: localize('gettingStarted.pickColor.description', "Pick a color theme to match your taste and mood while coding."),
button: { title: localize('gettingStarted.pickColor.button', "Pick a Theme"), command: 'workbench.action.selectTheme' },
doneOn: { eventFired: 'themeSelected' },
media: { type: 'image', altText: 'Color theme preview for dark and light theme.', path: 'colorTheme.jpg', }
},
{
id: 'findLanguageExtensions',
title: localize('gettingStarted.findLanguageExts.title', "Add more language & tools support"),
description: localize('gettingStarted.findLanguageExts.description', "VS Code supports almost every major programming language. While many are built-in, others can be installed as extensions with one click."),
title: localize('gettingStarted.findLanguageExts.title', "Code in any language, without switching editors"),
description: localize('gettingStarted.findLanguageExts.description', "VS Code supports over 50+ programming languages. While many are built-in, others can be easily installed as extensions in one click."),
button: {
title: localize('gettingStarted.findLanguageExts.button', "Browse Language Extensions"),
command: 'workbench.extensions.action.showLanguageExtensions',
@@ -139,7 +139,7 @@ export const content: GettingStartedContent = [
{
id: 'settingsSync',
title: localize('gettingStarted.settingsSync.title', "Sync your favorite setup"),
description: localize('gettingStarted.settingsSync.description', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings and installed extensions across several VS Code installations."),
description: localize('gettingStarted.settingsSync.description', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings & extensions across several VS Code instances."),
when: 'syncStatus != uninitialized',
button: {
title: localize('gettingStarted.settingsSync.button', "Enable Settings Sync"),
@@ -163,7 +163,7 @@ export const content: GettingStartedContent = [
{
id: 'pickAFolderTask-Other',
title: localize('gettingStarted.setup.OpenFolder.title', "Open your project"),
description: localize('gettingStarted.setup.OpenFolder.description', "Open a project folder to get started!"),
description: localize('gettingStarted.setup.OpenFolder.description2', "Open a folder to get started!"),
when: '!isMac',
button: {
title: localize('gettingStarted.setup.OpenFolder.button', "Pick a Folder"),
@@ -186,8 +186,8 @@ export const content: GettingStartedContent = [
items: [
{
id: 'commandPaletteTask',
title: localize('gettingStarted.commandPalette.title', "Find and run commands"),
description: localize('gettingStarted.commandPalette.description', "The easiest way to find everything VS Code can do. If you\'re ever looking for a feature or a shortcut, check here first!"),
title: localize('gettingStarted.commandPalette.title', "Find & run commands"),
description: localize('gettingStarted.commandPalette.description', "The easiest way to find everything VS Code can do. If you're ever looking for a feature or a shortcut, check here first!"),
button: {
title: localize('gettingStarted.commandPalette.button', "Open Command Palette"),
command: 'workbench.action.showCommands'
@@ -200,7 +200,7 @@ export const content: GettingStartedContent = [
title: localize('gettingStarted.terminal.title', "Run tasks in the integrated terminal"),
description: localize('gettingStarted.terminal.description', "Quickly run shell commands and monitor build output, right next to your code."),
button: {
title: localize('gettingStarted.terminal.button', "Open the Terminal"),
title: localize('gettingStarted.terminal.button', "Open Terminal"),
command: 'workbench.action.terminal.toggleTerminal'
},
doneOn: { commandExecuted: 'workbench.action.terminal.toggleTerminal' },
@@ -209,7 +209,7 @@ export const content: GettingStartedContent = [
{
id: 'extensions',
title: localize('gettingStarted.extensions.title', "Limitless extensibility"),
description: localize('gettingStarted.extensions.description', "Extensions are VS Code's power ups. They range from handy productivity hacks, expanding out-of-the-box features, to adding completely new capabilities."),
description: localize('gettingStarted.extensions.description', "Extensions are VS Code's power-ups. They range from handy productivity hacks, expanding out-of-the-box features, to adding completely new capabilities."),
button: {
title: localize('gettingStarted.extensions.button', "Browse Recommended Extensions"),
command: 'workbench.extensions.action.showRecommendedExtensions'
@@ -220,9 +220,9 @@ export const content: GettingStartedContent = [
{
id: 'settings',
title: localize('gettingStarted.settings.title', "Everything is a setting"),
description: localize('gettingStarted.settings.description', "Optimize every part of VS Code's look & feel to your liking. Enable Settings Sync lets you share your personal tweaks across machines."),
description: localize('gettingStarted.settings.description', "Optimize every part of VS Code's look & feel to your liking. Enabling Settings Sync lets you share your personal tweaks across machines."),
button: {
title: localize('gettingStarted.settings.button', "Tweak Some Settings"),
title: localize('gettingStarted.settings.button', "Tweak my Settings"),
command: 'workbench.action.openSettings'
},
doneOn: { commandExecuted: 'workbench.action.openSettings' },
@@ -77,6 +77,8 @@ export interface ICommonQueryProps<U extends UriComponents> {
excludePattern?: glob.IExpression;
extraFileResources?: U[];
onlyOpenEditors?: boolean;
maxResults?: number;
usingSearchPaths?: boolean;
}
@@ -372,6 +374,9 @@ export interface ISearchConfigurationProperties {
defaultNumberOfContextLines: number | null,
experimental: {}
};
experimental: {
searchInOpenEditors: boolean
}
sortOrder: SearchSortOrder;
}
@@ -407,21 +412,25 @@ export function pathIncludedInQuery(queryProps: ICommonQueryProps<URI>, fsPath:
return false;
}
if (queryProps.includePattern && !glob.match(queryProps.includePattern, fsPath)) {
return false;
}
if (queryProps.includePattern || queryProps.usingSearchPaths) {
if (queryProps.includePattern && glob.match(queryProps.includePattern, fsPath)) {
return true;
}
// If searchPaths are being used, the extra file must be in a subfolder and match the pattern, if present
if (queryProps.usingSearchPaths) {
return !!queryProps.folderQueries && queryProps.folderQueries.every(fq => {
const searchPath = fq.folder.fsPath;
if (extpath.isEqualOrParent(fsPath, searchPath)) {
const relPath = relative(searchPath, fsPath);
return !fq.includePattern || !!glob.match(fq.includePattern, relPath);
} else {
return false;
}
});
// If searchPaths are being used, the extra file must be in a subfolder and match the pattern, if present
if (queryProps.usingSearchPaths) {
return !!queryProps.folderQueries && queryProps.folderQueries.some(fq => {
const searchPath = fq.folder.fsPath;
if (extpath.isEqualOrParent(fsPath, searchPath)) {
const relPath = relative(searchPath, fsPath);
return !fq.includePattern || !!glob.match(fq.includePattern, relPath);
} else {
return false;
}
});
}
return false;
}
return true;
@@ -385,13 +385,7 @@ function getRgArgs(query: TextSearchQuery, options: TextSearchOptions): string[]
if (otherIncludes && otherIncludes.length) {
const uniqueOthers = new Set<string>();
otherIncludes.forEach(other => {
if (!other.endsWith('/**')) {
other += '/**';
}
uniqueOthers.add(other);
});
otherIncludes.forEach(other => { uniqueOthers.add(other); });
args.push('-g', '!*');
uniqueOthers
@@ -508,10 +502,6 @@ function getRgArgs(query: TextSearchQuery, options: TextSearchOptions): string[]
*/
export function spreadGlobComponents(globArg: string): string[] {
const components = splitGlobAware(globArg, '/');
if (components[components.length - 1] !== '**') {
components.push('**');
}
return components.map((_, i) => components.slice(0, i + 1).join('/'));
}
@@ -4,12 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { MirroredTestCollection } from 'vs/workbench/api/common/extHostTesting';
import { MirroredTestCollection, TestItemFilteredWrapper } from 'vs/workbench/api/common/extHostTesting';
import * as convert from 'vs/workbench/api/common/extHostTypeConverters';
import { TestDiffOpType } from 'vs/workbench/contrib/testing/common/testCollection';
import { stubTest, testStubs } from 'vs/workbench/contrib/testing/common/testStubs';
import { TestOwnedTestCollection, TestSingleUseCollection } from 'vs/workbench/contrib/testing/test/common/ownedTestCollection';
import { TestChangeEvent, TestItem } from 'vscode';
import { TestChangeEvent, TestItem, TextDocument } from 'vscode';
import { URI } from 'vs/base/common/uri';
import { Location } from 'vs/editor/common/modes';
import { Range } from 'vs/editor/common/core/range';
const simplify = (item: TestItem) => {
if ('toJSON' in item) {
@@ -262,5 +265,141 @@ suite('ExtHost Testing', () => {
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root');
});
});
suite('TestItemFilteredWrapper', () => {
const stubTestWithLocation = (label: string, location: Location): TestItem => {
const t = stubTest(label);
t.location = location as any;
return t;
};
const location1: Location = {
range: new Range(0, 0, 0, 0),
uri: URI.parse('file:///foo.ts')
};
const location2: Location = {
range: new Range(0, 0, 0, 0),
uri: URI.parse('file:///bar.ts')
};
const location3: Location = {
range: new Range(0, 0, 0, 0),
uri: URI.parse('file:///baz.ts')
};
const textDocumentFilter = {
uri: location1.uri
} as TextDocument;
let testsWithLocation: TestItem;
setup(() => {
testsWithLocation = {
...stubTest('root'),
children: [
{
...stubTestWithLocation('a', location1),
children: [stubTestWithLocation('aa', location1), stubTestWithLocation('ab', location1)]
},
{
...stubTestWithLocation('b', location2),
children: [stubTestWithLocation('ba', location2), stubTestWithLocation('bb', location2)]
},
{
...stubTestWithLocation('b', location3),
}
],
};
});
teardown(() => {
TestItemFilteredWrapper.removeFilter(textDocumentFilter);
});
test('gets all actual properties', () => {
const testItem: TestItem = stubTest('test1');
const wrapper: TestItemFilteredWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testItem, textDocumentFilter);
assert.strictEqual(testItem.debuggable, wrapper.debuggable);
assert.strictEqual(testItem.description, wrapper.description);
assert.strictEqual(testItem.label, wrapper.label);
assert.strictEqual(testItem.location, wrapper.location);
assert.strictEqual(testItem.runnable, wrapper.runnable);
assert.strictEqual(testItem.state, wrapper.state);
});
test('gets no children if nothing matches Uri filter', () => {
let tests: TestItem = testStubs.nested();
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(tests, textDocumentFilter);
assert.strictEqual(wrapper.children.length, 0);
});
test('filter is applied to children', () => {
const wrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
assert.strictEqual(wrapper.label, 'root');
assert.strictEqual(wrapper.children.length, 1);
assert.strictEqual(wrapper.children[0] instanceof TestItemFilteredWrapper, true);
assert.strictEqual(wrapper.children[0].label, 'a');
});
test('can get if node has matching filter', () => {
const rootWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
const invisible = testsWithLocation.children![1];
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
const visible = testsWithLocation.children![0];
const visibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(visible, textDocumentFilter);
// The root is always visible
assert.strictEqual(rootWrapper.hasNodeMatchingFilter, true);
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, false);
assert.strictEqual(visibleWrapper.hasNodeMatchingFilter, true);
});
test('can get visible parent', () => {
const rootWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
const invisible = testsWithLocation.children![1];
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
const visible = testsWithLocation.children![0];
const visibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(visible, textDocumentFilter);
// The root is always visible
assert.strictEqual(rootWrapper.visibleParent, rootWrapper);
assert.strictEqual(invisibleWrapper.visibleParent, rootWrapper);
assert.strictEqual(visibleWrapper.visibleParent, visibleWrapper);
});
test('can reset cached value of hasNodeMatchingFilter', () => {
TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
const invisible = testsWithLocation.children![1];
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, false);
invisible.location = location1 as any;
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, false);
invisibleWrapper.reset();
assert.strictEqual(invisibleWrapper.hasNodeMatchingFilter, true);
});
test('can reset cached value of hasNodeMatchingFilter of parents up to visible parent', () => {
const rootWrapper = TestItemFilteredWrapper.getWrapperForTestItem(testsWithLocation, textDocumentFilter);
const invisibleParent = testsWithLocation.children![1];
const invisibleParentWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisibleParent, textDocumentFilter);
const invisible = invisibleParent.children![1];
const invisibleWrapper = TestItemFilteredWrapper.getWrapperForTestItem(invisible, textDocumentFilter);
assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, false);
invisible.location = location1 as any;
assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, false);
invisibleWrapper.reset();
assert.strictEqual(invisibleParentWrapper.hasNodeMatchingFilter, true);
// the root should be undefined due to the reset.
assert.strictEqual((rootWrapper as any).matchesFilter, undefined);
});
});
});
});
@@ -19,7 +19,7 @@ import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { IModelService } from 'vs/editor/common/services/modelService';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { TestFileService, TestEditorService, TestEditorGroupsService, TestEnvironmentService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestFileService, TestEditorService, TestEditorGroupsService, TestEnvironmentService, TestLifecycleService } from 'vs/workbench/test/browser/workbenchTestServices';
import { BulkEditService } from 'vs/workbench/contrib/bulkEdit/browser/bulkEditService';
import { NullLogService, ILogService } from 'vs/platform/log/common/log';
import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
@@ -52,6 +52,7 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/ur
import { extUri } from 'vs/base/common/resources';
import { ITextSnapshot } from 'vs/editor/common/model';
import { VSBuffer, VSBufferReadable } from 'vs/base/common/buffer';
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
suite('MainThreadEditors', () => {
@@ -94,6 +95,7 @@ suite('MainThreadEditors', () => {
services.set(ICodeEditorService, new TestCodeEditorService());
services.set(IFileService, new TestFileService());
services.set(IEditorService, new TestEditorService());
services.set(ILifecycleService, new TestLifecycleService());
services.set(IEditorGroupsService, new TestEditorGroupsService());
services.set(ITextFileService, new class extends mock<ITextFileService>() {
isDirty() { return false; }
@@ -15,6 +15,8 @@ export function setup() {
return;
}
await app.workbench.settingsEditor.addUserSetting('webview.experimental.useIframes', 'true');
await app.workbench.extensions.openExtensionsViewlet();
await app.workbench.extensions.installExtension('michelkaporin.vscode-smoketest-check', true);
@@ -27,5 +29,11 @@ export function setup() {
await app.workbench.quickaccess.runCommand('Smoke Test Check');
await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check');
});
after(async function () {
const app = this.app as Application;
await app.workbench.settingsEditor.clearUserSettings();
});
});
}
+1937 -2494
View File
File diff suppressed because it is too large Load Diff