update vscode

This commit is contained in:
Siheng Zhao
2024-01-08 23:09:12 +08:00
parent 2b09b7ce41
commit 4f165cd618
1951 changed files with 303273 additions and 12 deletions

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};

418
vscodeEvalExtension/node_modules/@vscode/test-cli/out/bin.mjs generated vendored Executable file
View File

@@ -0,0 +1,418 @@
#!/usr/bin/env node
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import * as chokidar from 'chokidar';
import { existsSync, promises as fs } from 'fs';
import { glob } from 'glob';
import { minimatch } from 'minimatch';
import { cpus } from 'os';
import { dirname, isAbsolute, join, resolve } from 'path';
import supportsColor from 'supports-color';
import { fileURLToPath, pathToFileURL } from 'url';
import yargs from 'yargs';
const rulesAndBehavior = 'Mocha: Rules & Behavior';
const reportingAndOutput = 'Mocha: Reporting & Output';
const fileHandling = 'Mocha: File Handling';
const testFilters = 'Mocha: Test Filters';
const vscodeSection = 'VS Code Options';
const configFileDefault = 'nearest .vscode-test.js';
const args = yargs(process.argv)
.epilogue('See https://code.visualstudio.com/api/working-with-extensions/testing-extension for help')
.option('config', {
type: 'string',
description: 'Config file to use',
default: configFileDefault,
group: vscodeSection,
})
.option('label', {
alias: 'l',
type: 'array',
description: 'Specify the test configuration to run based on its label in configuration',
group: vscodeSection,
})
.option('code-version', {
type: 'string',
description: 'Override the VS Code version used to run tests',
group: vscodeSection,
})
//#region Rules & Behavior
.option('bail', {
alias: 'b',
type: 'boolean',
description: 'Abort ("bail") after first test failure',
group: rulesAndBehavior,
})
.option('dry-run', {
type: 'boolean',
description: 'Report tests without executing them',
group: rulesAndBehavior,
})
.option('list-configuration', {
type: 'boolean',
description: 'List configurations and that they woud run, without executing them',
group: rulesAndBehavior,
})
.option('fail-zero', {
type: 'boolean',
description: 'Fail test run if no test(s) encountered',
group: rulesAndBehavior,
})
.option('forbid-only', {
type: 'boolean',
description: 'Fail if exclusive test(s) encountered',
group: rulesAndBehavior,
})
.option('forbid-pending', {
type: 'boolean',
description: 'Fail if pending test(s) encountered',
group: rulesAndBehavior,
})
.option('jobs', {
alias: 'j',
type: 'number',
description: 'Number of concurrent jobs for --parallel; use 1 to run in serial',
default: Math.max(1, cpus().length - 1),
group: rulesAndBehavior,
})
.options('parallel', {
alias: 'p',
type: 'boolean',
description: 'Run tests in parallel',
group: rulesAndBehavior,
})
.option('retries', {
alias: 'r',
type: 'number',
description: 'Number of times to retry failed tests',
group: rulesAndBehavior,
})
.option('slow', {
alias: 's',
type: 'number',
description: 'Specify "slow" test threshold (in milliseconds)',
default: 75,
group: rulesAndBehavior,
})
.option('timeout', {
alias: 't',
type: 'number',
description: 'Specify test timeout threshold (in milliseconds)',
default: 2000,
group: rulesAndBehavior,
})
//#endregion
//#region Reporting & Output
.option('color', {
alias: 'c',
type: 'boolean',
description: 'Force-enable color output',
group: reportingAndOutput,
})
.option('diff', {
type: 'boolean',
description: 'Show diff on failure',
default: true,
group: reportingAndOutput,
})
.option('full-trace', {
type: 'boolean',
description: 'Display full stack traces',
group: reportingAndOutput,
})
.option('inline-diffs', {
type: 'boolean',
description: 'Display actual/expected differences inline within each string',
group: reportingAndOutput,
})
.option('reporter', {
alias: 'R',
type: 'string',
description: 'Specify reporter to use',
default: 'spec',
group: reportingAndOutput,
})
.option('reporter-option', {
alias: 'O',
type: 'array',
description: 'Reporter-specific options (<k=v,[k1=v1,..]>)',
group: reportingAndOutput,
})
//#endregion
//#region File Handling
.option('file', {
type: 'array',
description: 'Specify file(s) to be loaded prior to root suite',
group: fileHandling,
})
.option('ignore', {
alias: 'exclude',
type: 'array',
description: 'Ignore file(s) or glob pattern(s)',
group: fileHandling,
})
.option('watch', {
alias: 'w',
type: 'boolean',
description: 'Watch files in the current working directory for changes',
group: fileHandling,
})
.option('watch-files', {
type: 'array',
description: 'List of paths or globs to watch',
group: fileHandling,
})
.option('watch-ignore', {
type: 'array',
description: 'List of paths or globs to exclude from watching',
group: fileHandling,
})
.option('run', {
type: 'array',
description: 'List of specific files to run',
group: fileHandling,
})
//#endregion
//#region Test Filters
.option('fgrep', {
type: 'string',
alias: 'f',
description: 'Only run tests containing this string',
group: testFilters,
})
.option('grep', {
type: 'string',
alias: 'g',
description: 'Only run tests matching this string or regexp',
group: testFilters,
})
.option('invert', {
alias: 'i',
type: 'boolean',
description: 'Inverts --grep and --fgrep matches',
group: testFilters,
})
.parseSync();
const configFileRules = {
json: (path) => fs.readFile(path, 'utf8').then(JSON.parse),
js: (path) => import(pathToFileURL(path).toString()),
mjs: (path) => import(pathToFileURL(path).toString()),
};
class CliExpectedError extends Error {
}
main();
async function main() {
let code = 0;
try {
let configs = args.config !== configFileDefault
? await tryLoadConfigFile(args.config)
: await loadDefaultConfigFile();
if (args.label?.length) {
configs = args.label.map((label) => {
const found = configs.find((c, i) => typeof label === 'string' ? c.config.label === label : i === label);
if (!found) {
throw new CliExpectedError(`Could not find a configuration with label "${label}"`);
}
return found;
});
}
if (args.watch) {
await watchConfigs(configs);
}
else {
code = await runConfigs(configs);
}
}
catch (e) {
code = 1;
if (e instanceof CliExpectedError) {
console.error(e.message);
}
else {
console.error(e.stack || e);
}
}
finally {
process.exit(code);
}
}
const WATCH_RUN_DEBOUNCE = 500;
async function watchConfigs(configs) {
let debounceRun;
let rerun = false;
let running = true;
const runOrDebounce = () => {
if (debounceRun) {
clearTimeout(debounceRun);
}
debounceRun = setTimeout(async () => {
running = true;
rerun = false;
try {
await runConfigs(configs);
}
finally {
running = false;
if (rerun) {
runOrDebounce();
}
}
}, WATCH_RUN_DEBOUNCE);
};
const watcher = chokidar.watch(args.watchFiles?.length ? args.watchFiles.map(String) : process.cwd(), {
ignored: [
'**/.vscode-test/**',
'**/node_modules/**',
...(args.watchIgnore || []).map(String),
],
ignoreInitial: true,
});
watcher.on('all', (evts) => {
console.log(evts);
if (running) {
rerun = true;
}
else {
runOrDebounce();
}
});
watcher.on('ready', () => {
runOrDebounce();
});
// wait until interrupted
await new Promise(() => {
/* no-op */
});
}
const isDesktop = (config) => !config.platform || config.platform === 'desktop';
const RUNNER_PATH = join(fileURLToPath(new URL('.', import.meta.url)), 'runner.cjs');
/** Runs the given test configurations. */
async function runConfigs(configs) {
const resolvedConfigs = await Promise.all(configs.map(async (c) => {
const files = args.run?.length
? args.run.map((r) => resolve(process.cwd(), String(r)))
: await gatherFiles(c);
const env = {};
if (isDesktop(c.config)) {
c.config.launchArgs ||= [];
if (c.config.workspaceFolder) {
c.config.launchArgs.push(resolve(dirname(c.path), c.config.workspaceFolder));
}
env.VSCODE_TEST_OPTIONS = JSON.stringify({
mochaOpts: { ...args, ...c.config.mocha },
colorDefault: supportsColor.stdout || process.env.MOCHA_COLORS !== undefined,
preload: [
...(typeof c.config.mocha?.preload === 'string'
? [c.config.mocha.preload]
: c.config.mocha?.preload || []).map((f) => require.resolve(f, { paths: [c.path] })),
...(args.file?.map((f) => require.resolve(String(f), { paths: [process.cwd()] })) ||
[]),
],
files,
});
}
return {
...c,
files,
env,
extensionTestsPath: RUNNER_PATH,
extensionDevelopmentPath: c.config.extensionDevelopmentPath?.slice() || dirname(c.path),
};
}));
if (args.listConfiguration) {
console.log(JSON.stringify(resolvedConfigs, null, 2));
return 0;
}
let code = 0;
for (const { config, path, env, extensionTestsPath } of resolvedConfigs) {
if (isDesktop(config)) {
let electron;
try {
electron = await import('@vscode/test-electron');
}
catch (e) {
throw new CliExpectedError('@vscode/test-electron not found, you may need to install it ("npm install -D @vscode/test-electron")');
}
const nextCode = await electron.runTests({
...config,
version: args.codeVersion || config.version,
extensionDevelopmentPath: config.extensionDevelopmentPath?.slice() || dirname(path),
extensionTestsPath,
extensionTestsEnv: { ...config.env, ...env, ELECTRON_RUN_AS_NODE: undefined },
launchArgs: [...(config.launchArgs || [])],
platform: config.desktopPlatform,
reporter: config.download?.reporter,
timeout: config.download?.timeout,
reuseMachineInstall: config.useInstallation && 'fromMachine' in config.useInstallation
? config.useInstallation.fromMachine
: undefined,
vscodeExecutablePath: config.useInstallation && 'fromPath' in config.useInstallation
? config.useInstallation.fromPath
: undefined,
});
if (nextCode > 0 && args.bail) {
return nextCode;
}
code = Math.max(code, nextCode);
}
}
return code;
}
/** Gathers test files that match the config */
async function gatherFiles({ config, path }) {
const fileListsProms = [];
const cwd = dirname(path);
const ignoreGlobs = args.ignore?.map(String).filter((p) => !isAbsolute(p));
for (const file of config.files instanceof Array ? config.files : [config.files]) {
if (isAbsolute(file)) {
if (!ignoreGlobs?.some((i) => minimatch(file, i))) {
fileListsProms.push([file]);
}
}
else {
fileListsProms.push(glob(file, { cwd, ignore: ignoreGlobs }).then((l) => l.map((f) => join(cwd, f))));
}
}
const files = new Set((await Promise.all(fileListsProms)).flat());
args.ignore?.forEach((i) => files.delete(i));
return [...files];
}
/** Loads a specific config file by the path, throwing if loading fails. */
async function tryLoadConfigFile(path) {
const ext = path.split('.').pop();
if (!configFileRules.hasOwnProperty(ext)) {
throw new CliExpectedError(`I don't know how to load the extension '${ext}'. We can load: ${Object.keys(configFileRules).join(', ')}`);
}
try {
let loaded = await configFileRules[ext](path);
if ('default' in loaded) {
// handle default es module exports
loaded = loaded.default;
}
// allow returned promises to resolve:
loaded = await loaded;
return (Array.isArray(loaded) ? loaded : [loaded]).map((config) => ({ config, path }));
}
catch (e) {
throw new CliExpectedError(`Could not read config file ${path}: ${e.stack || e}`);
}
}
/** Loads the default config based on the process working directory. */
async function loadDefaultConfigFile() {
const base = '.vscode-test';
let dir = process.cwd();
while (true) {
for (const ext of Object.keys(configFileRules)) {
const candidate = join(dir, `${base}.${ext}`);
if (existsSync(candidate)) {
return tryLoadConfigFile(candidate);
}
}
const next = dirname(dir);
if (next === dir) {
break;
}
dir = next;
}
throw new CliExpectedError(`Could not find a ${base} file in this directory or any parent. You can specify one with the --config option.`);
}

View File

@@ -0,0 +1,5 @@
"use strict";
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,124 @@
/// <reference types="mocha" />
import { ProgressReporter } from '@vscode/test-electron';
export interface IBaseTestConfiguration {
/**
* A file or list of files in which to find tests. Non-absolute paths will
* be treated as glob expressions relative to the location of
* the `.vscode-test.js` file.
*/
files: string | readonly string[];
/**
* Version to download and install. This may be:
* - A quality, like `stable` or `insiders`
* - A version number, like `1.82.0`
* - A commit hash of a version to install
*
* Defaults to `stable`, which is latest stable version.
*/
version?: 'insiders' | 'stable' | string;
/**
* Defines extension directories to load during tests. Defaults to the directory
* of the `.vscode-test.js` file. Must include a `package.json` Extension Manifest.
*/
extensionDevelopmentPath?: string | readonly string[];
/**
* Path to a folder or workspace file that should be opened.
*/
workspaceFolder?: string;
/**
* Additional options to pass to the Mocha runner. Any options given on the
* command line will be merged into and override these defaults.
* @see https://mochajs.org/api/mocha
*/
mocha?: Mocha.MochaOptions & {
/**
* Specify file(s) to be loaded prior to root suite.
*/
preload?: string | string[];
};
/**
* Optional label for this configuration, which can be used to specify which
* configuration to run if multiple configurations are provided.
*/
label?: string;
}
export interface IDesktopTestConfiguration extends IBaseTestConfiguration {
/**
* Platform to use for running the tests.
*/
platform?: 'desktop';
/**
* The VS Code desktop platform to download. If not specified, it defaults
* to the current platform.
*
* Possible values are:
* - `win32-archive`
* - `win32-x64-archive`
* - `win32-arm64-archive `
* - `darwin`
* - `darwin-arm64`
* - `linux-x64`
* - `linux-arm64`
* - `linux-armhf`
*/
desktopPlatform?: string;
/**
* A list of launch arguments passed to VS Code executable, in addition to `--extensionDevelopmentPath`
* and `--extensionTestsPath` which are provided by `extensionDevelopmentPath` and `extensionTestsPath`
* options.
*
* If the first argument is a path to a file/folder/workspace, the launched VS Code instance
* will open it.
*
* See `code --help` for possible arguments.
*/
launchArgs?: string[];
/**
* Environment variables to set when running the test.
*/
env?: Record<string, string | undefined>;
/**
* Configures a specific VS Code installation to use instead of automatically
* downloading the {@link version}
*/
useInstallation?: {
/**
* Whether VS Code should be launched using default settings and extensions
* installed on this machine. If `false`, then separate directories will be
* used inside the `.vscode-test` folder within the project.
*
* Defaults to `false`.
*/
fromMachine: boolean;
} | {
/**
* The VS Code executable path used for testing.
*
* If not passed, will use `options.version` to download a copy of VS Code for testing.
* If `version` is not specified either, will download and use latest stable release.
*/
fromPath?: string;
};
download?: {
/**
* Progress reporter to use while VS Code is downloaded. Defaults to a
* console reporter. A {@link SilentReporter} is also available, and you
* may implement your own.
*/
reporter: ProgressReporter;
/**
* Number of milliseconds after which to time out if no data is received from
* the remote when downloading VS Code. Note that this is an 'idle' timeout
* and does not enforce the total time VS Code may take to download.
*/
timeout?: number;
};
}
/**
* Configuration that runs in browsers.
* @todo: this is incomplete, and does not yet function
*/
export interface IWebTestConfiguration extends IBaseTestConfiguration {
platform: 'firefox' | 'webkit' | 'chromium';
}
export type TestConfiguration = IDesktopTestConfiguration | IWebTestConfiguration;

View File

@@ -0,0 +1,80 @@
"use strict";
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
const Mocha = __importStar(require("mocha"));
const util_1 = require("util");
const fullJsonStreamReporterTypes_cjs_1 = require("./fullJsonStreamReporterTypes.cjs");
__exportStar(require("./fullJsonStreamReporterTypes.cjs"), exports);
/**
* Similar to the mocha JSON stream, but includes additional information
* on failure and when tests run. Specifically, the mocha json-stream does not
* include unmangled expected versus actual results.
*
* Writes a superset of the data that json-stream normally would.
*/
module.exports = class FullJsonStreamReporter {
constructor(runner) {
const total = runner.total;
runner.once(Mocha.Runner.constants.EVENT_RUN_BEGIN, () => writeEvent([fullJsonStreamReporterTypes_cjs_1.MochaEvent.Start, { total }]));
runner.once(Mocha.Runner.constants.EVENT_RUN_END, () => writeEvent([fullJsonStreamReporterTypes_cjs_1.MochaEvent.End, {}]));
runner.on(Mocha.Runner.constants.EVENT_SUITE_BEGIN, (suite) => writeEvent([fullJsonStreamReporterTypes_cjs_1.MochaEvent.SuiteStart, { path: suite.titlePath(), file: suite.file }]));
runner.on(Mocha.Runner.constants.EVENT_TEST_BEGIN, (test) => writeEvent([fullJsonStreamReporterTypes_cjs_1.MochaEvent.TestStart, clean(test)]));
runner.on(Mocha.Runner.constants.EVENT_TEST_PASS, (test) => writeEvent([fullJsonStreamReporterTypes_cjs_1.MochaEvent.Pass, clean(test)]));
runner.on(Mocha.Runner.constants.EVENT_TEST_FAIL, (test, err) => {
writeEvent([
fullJsonStreamReporterTypes_cjs_1.MochaEvent.Fail,
{
...clean(test),
actual: (0, util_1.inspect)(err.actual, { depth: 30 }),
expected: (0, util_1.inspect)(err.expected, { depth: 30 }),
err: err.message,
stack: err.stack || null,
},
]);
});
}
};
function writeEvent(event) {
process.stdout.write(JSON.stringify(event) + '\n');
}
const clean = (test) => {
return {
path: test.titlePath(),
duration: test.duration,
currentRetry: test.currentRetry(),
file: test.file,
speed: !test.duration || test.duration < test.slow() / 2
? 'fast'
: test.duration > test.slow()
? 'slow'
: 'medium',
};
};

View File

@@ -0,0 +1 @@
export * from './fullJsonStreamReporterTypes.cjs';

View File

@@ -0,0 +1,15 @@
"use strict";
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MochaEvent = void 0;
var MochaEvent;
(function (MochaEvent) {
MochaEvent["Start"] = "start";
MochaEvent["TestStart"] = "testStart";
MochaEvent["Pass"] = "pass";
MochaEvent["Fail"] = "fail";
MochaEvent["End"] = "end";
MochaEvent["SuiteStart"] = "suiteStart";
})(MochaEvent || (exports.MochaEvent = MochaEvent = {}));

View File

@@ -0,0 +1,33 @@
export declare enum MochaEvent {
Start = "start",
TestStart = "testStart",
Pass = "pass",
Fail = "fail",
End = "end",
SuiteStart = "suiteStart"
}
export interface IStartEvent {
total: number;
}
export interface ITestStartEvent {
path: string[];
currentRetry: number;
file?: string;
}
export interface IPassEvent extends ITestStartEvent {
duration?: number;
speed: 'fast' | 'medium' | 'slow';
}
export interface IFailEvent extends IPassEvent {
err: string;
stack: string | null;
expected?: string;
actual?: string;
}
export interface IEndEvent {
}
export interface ISuiteStartEvent {
path: string[];
file?: string;
}
export type MochaEventTuple = [MochaEvent.Start, IStartEvent] | [MochaEvent.TestStart, ITestStartEvent] | [MochaEvent.Pass, IPassEvent] | [MochaEvent.Fail, IFailEvent] | [MochaEvent.End, IEndEvent] | [MochaEvent.SuiteStart, ISuiteStartEvent];

View File

@@ -0,0 +1,25 @@
"use strict";
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineConfig = void 0;
__exportStar(require("./config.cjs"), exports);
// todo: can be removed if/when the extension uses Node16+ resolution
__exportStar(require("./fullJsonStreamReporterTypes.cjs"), exports);
const defineConfig = (config) => config;
exports.defineConfig = defineConfig;

View File

@@ -0,0 +1,6 @@
import { TestConfiguration } from './config.cjs';
export * from './config.cjs';
export * from './fullJsonStreamReporterTypes.cjs';
type AnyConfiguration = TestConfiguration | TestConfiguration[];
type AnyConfigurationOrPromise = AnyConfiguration | Promise<AnyConfiguration>;
export declare const defineConfig: (config: AnyConfigurationOrPromise | (() => AnyConfigurationOrPromise)) => AnyConfigurationOrPromise | (() => AnyConfigurationOrPromise);

View File

@@ -0,0 +1 @@
export * from './index.cjs';

View File

@@ -0,0 +1,4 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
export * from './index.cjs';

View File

@@ -0,0 +1,27 @@
"use strict";
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const mocha_1 = __importDefault(require("mocha"));
async function run() {
const { mochaOpts, files, preload, colorDefault, } = JSON.parse(process.env.VSCODE_TEST_OPTIONS);
// Create the mocha test
const mocha = new mocha_1.default({
ui: 'tdd',
color: colorDefault,
...mochaOpts,
});
for (const file of preload) {
require(file);
}
for (const file of files) {
mocha.addFile(file);
}
await new Promise((resolve, reject) => mocha.run((failures) => failures ? reject(failures > 1 ? `${failures} tests failed.` : `${failures} test failed.`) : resolve()));
}
exports.run = run;

View File

@@ -0,0 +1 @@
export declare function run(): Promise<void>;