Revert "Merge from vscode merge-base (#22769)" (#22779)

This reverts commit 6bd0a17d3c.
This commit is contained in:
Karl Burtram
2023-04-18 21:44:05 -07:00
committed by GitHub
parent 6bd0a17d3c
commit 47a1745180
2389 changed files with 42588 additions and 92170 deletions

View File

@@ -10,9 +10,7 @@ import { Logger, measureAndLog } from './logger';
export const enum Quality {
Dev,
Insiders,
Stable,
Exploration,
OSS
Stable
}
export interface ApplicationOptions extends LaunchOptions {
@@ -109,7 +107,7 @@ export class Application {
extraArgs: [...(this.options.extraArgs || []), ...extraArgs],
});
this._workbench = new Workbench(this._code);
this._workbench = new Workbench(this._code, this.userDataPath);
return code;
}

View File

@@ -20,7 +20,6 @@ export interface LaunchOptions {
readonly extensionsPath: string;
readonly logger: Logger;
logsPath: string;
crashesPath: string;
readonly verbose?: boolean;
readonly extraArgs?: string[];
readonly remote?: boolean;
@@ -158,6 +157,11 @@ export class Code {
});
}
if (retries === 40) {
done = true;
reject(new Error('Smoke test exit call did not terminate process after 20s, giving up'));
}
try {
process.kill(pid, 0); // throws an exception if the process doesn't exist anymore.
await new Promise(resolve => setTimeout(resolve, 500));
@@ -165,12 +169,6 @@ export class Code {
done = true;
resolve();
}
if (retries === 60) {
done = true;
this.logger.log('Smoke test exit call did not terminate process after 30s, giving up');
resolve();
}
}
})();
}), 'Code#exit()', this.logger);

View File

@@ -85,9 +85,6 @@ export class Editor {
}
async waitForTypeInEditor(filename: string, text: string, selectorPrefix = ''): Promise<any> {
if (text.includes('\n')) {
throw new Error('waitForTypeInEditor does not support new lines, use either a long single line or dispatchKeybinding(\'Enter\')');
}
const editor = [selectorPrefix || '', EDITOR(filename)].join(' ');
await this.code.waitForElement(editor);

View File

@@ -19,7 +19,7 @@ export interface IElectronConfiguration {
}
export async function resolveElectronConfiguration(options: LaunchOptions): Promise<IElectronConfiguration> {
const { codePath, workspacePath, extensionsPath, userDataDir, remote, logger, logsPath, crashesPath, extraArgs } = options;
const { codePath, workspacePath, extensionsPath, userDataDir, remote, logger, logsPath, extraArgs } = options;
const env = { ...process.env };
const args = [
@@ -30,7 +30,7 @@ export async function resolveElectronConfiguration(options: LaunchOptions): Prom
'--no-cached-data',
'--disable-updates',
'--disable-keytar',
`--crash-reporter-directory=${crashesPath}`,
'--disable-crash-reporter',
'--disable-workspace-trust',
`--extensions-dir=${extensionsPath}`,
`--user-data-dir=${userDataDir}`,
@@ -42,11 +42,7 @@ export async function resolveElectronConfiguration(options: LaunchOptions): Prom
}
if (process.platform === 'linux') {
// --disable-dev-shm-usage: when run on docker containers where size of /dev/shm
// partition < 64MB which causes OOM failure for chromium compositor that uses
// this partition for shared memory.
// Refs https://github.com/microsoft/vscode/issues/152143
args.push('--disable-dev-shm-usage');
args.push('--disable-gpu'); // Linux has trouble in VMs to render properly with GPU enabled
}
if (remote) {

View File

@@ -61,7 +61,7 @@ export class Extensions extends Viewlet {
await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[data-extension-id="${id}"] .extension-list-item .monaco-action-bar .action-item:not(.disabled) .extension-action.install`);
await this.code.waitForElement(`.extension-editor .monaco-action-bar .action-item:not(.disabled) .extension-action.uninstall`);
if (waitUntilEnabled) {
await this.code.waitForElement(`.extension-editor .monaco-action-bar .action-item:not(.disabled)[title="Disable this extension"]`);
await this.code.waitForElement(`.extension-editor .monaco-action-bar .action-item:not(.disabled) .extension-action[title="Disable this extension"]`);
}
}
}

View File

@@ -25,7 +25,6 @@ export * from './terminal';
export * from './viewlet';
export * from './localization';
export * from './workbench';
export * from './task';
export { getDevElectronPath, getBuildElectronPath, getBuildVersion } from './electron';
// {{SQL CARBON EDIT}}

View File

@@ -44,7 +44,7 @@ async function launchServer(options: LaunchOptions) {
const args = [
'--disable-telemetry',
'--disable-workspace-trust',
`--port=${port++}`,
`--port${port++}`,
'--enable-smoke-test-driver',
`--extensions-dir=${extensionsPath}`,
`--server-data-dir=${agentFolder}`,

View File

@@ -32,12 +32,12 @@ export class Problems {
}
static getSelectorInProblemsView(problemType: ProblemSeverity): string {
const selector = problemType === ProblemSeverity.WARNING ? 'codicon-warning' : 'codicon-error';
let selector = problemType === ProblemSeverity.WARNING ? 'codicon-warning' : 'codicon-error';
return `div[id="workbench.panel.markers"] .monaco-tl-contents .marker-icon.${selector}`;
}
static getSelectorInEditor(problemType: ProblemSeverity): string {
const selector = problemType === ProblemSeverity.WARNING ? 'squiggly-warning' : 'squiggly-error';
let selector = problemType === ProblemSeverity.WARNING ? 'squiggly-warning' : 'squiggly-error';
return `.view-overlays .cdr.${selector}`;
}
}

View File

@@ -3,6 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import * as path from 'path';
import { Editor } from './editor';
import { Editors } from './editors';
import { Code } from './code';
@@ -10,14 +12,8 @@ import { QuickAccess } from './quickaccess';
export class SettingsEditor {
constructor(private code: Code, private editors: Editors, private editor: Editor, private quickaccess: QuickAccess) { }
constructor(private code: Code, private userDataPath: string, private editors: Editors, private editor: Editor, private quickaccess: QuickAccess) { }
/**
* Write a single setting key value pair.
*
* Warning: You may need to set `editor.wordWrap` to `"on"` if this is called with a really long
* setting.
*/
async addUserSetting(setting: string, value: string): Promise<void> {
await this.openUserSettingsFile();
@@ -26,27 +22,12 @@ export class SettingsEditor {
await this.editors.saveOpenedFile();
}
/**
* Write several settings faster than multiple calls to {@link addUserSetting}.
*
* Warning: You will likely also need to set `editor.wordWrap` to `"on"` if `addUserSetting` is
* called after this in the test.
*/
async addUserSettings(settings: [key: string, value: string][]): Promise<void> {
await this.openUserSettingsFile();
await this.code.dispatchKeybinding('right');
await this.editor.waitForTypeInEditor('settings.json', settings.map(v => `"${v[0]}": ${v[1]},`).join(''));
await this.editors.saveOpenedFile();
}
async clearUserSettings(): Promise<void> {
const settingsPath = path.join(this.userDataPath, 'User', 'settings.json');
await new Promise<void>((c, e) => fs.writeFile(settingsPath, '{\n}', 'utf8', err => err ? e(err) : c()));
await this.openUserSettingsFile();
await this.quickaccess.runCommand('editor.action.selectAll');
await this.code.dispatchKeybinding('Delete');
await this.editor.waitForTypeInEditor('settings.json', `{`); // will auto close }
await this.editors.saveOpenedFile();
await this.quickaccess.runCommand('workbench.action.closeActiveEditor');
await this.editor.waitForEditorContents('settings.json', c => c === '{}');
}
async openUserSettingsFile(): Promise<void> {

View File

@@ -1,86 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Editor } from './editor';
import { Code } from './code';
import { QuickAccess } from './quickaccess';
import { Editors } from './editors';
import { QuickInput } from './quickinput';
import { Terminal } from './terminal';
interface ITaskConfigurationProperties {
label?: string;
type?: string;
command?: string;
identifier?: string;
group?: string;
isBackground?: boolean;
promptOnClose?: boolean;
icon?: { id?: string; color?: string };
hide?: boolean;
}
export enum TaskCommandId {
TerminalRename = 'workbench.action.terminal.rename'
}
export class Task {
constructor(private code: Code, private editor: Editor, private editors: Editors, private quickaccess: QuickAccess, private quickinput: QuickInput, private terminal: Terminal) {
}
async assertTasks(filter: string, expected: ITaskConfigurationProperties[], type: 'run' | 'configure') {
await this.code.dispatchKeybinding('right');
await this.editors.saveOpenedFile();
type === 'run' ? await this.quickaccess.runCommand('workbench.action.tasks.runTask', true) : await this.quickaccess.runCommand('workbench.action.tasks.configureTask', true);
if (expected.length === 0) {
await this.quickinput.waitForQuickInputElements(e => e.length > 1 && e.every(label => label.trim() !== filter.trim()));
} else {
await this.quickinput.waitForQuickInputElements(e => e.length > 1 && e.some(label => label.trim() === filter.trim()));
}
if (expected.length > 0 && !expected[0].hide) {
// select the expected task
await this.quickinput.selectQuickInputElement(0, true);
// Continue without scanning the output
await this.quickinput.selectQuickInputElement(0);
if (expected[0].icon) {
await this.terminal.assertSingleTab({ color: expected[0].icon.color, icon: expected[0].icon.id || 'tools' });
}
}
await this.quickinput.closeQuickInput();
}
async configureTask(properties: ITaskConfigurationProperties) {
await this.quickaccess.openFileQuickAccessAndWait('tasks.json', 'tasks.json');
await this.quickinput.selectQuickInputElement(0);
await this.quickaccess.runCommand('editor.action.selectAll');
await this.code.dispatchKeybinding('Delete');
const taskStringLines: string[] = [
'{', // Brackets auto close
'"version": "2.0.0",',
'"tasks": [{' // Brackets auto close
];
for (let [key, value] of Object.entries(properties)) {
if (typeof value === 'object') {
value = JSON.stringify(value);
} else if (typeof value === 'boolean') {
value = value;
} else if (typeof value === 'string') {
value = `"${value}"`;
} else {
throw new Error('Unsupported task property value type');
}
taskStringLines.push(`"${key}": ${value},`);
}
for (const [i, line] of taskStringLines.entries()) {
await this.editor.waitForTypeInEditor('tasks.json', `${line}`);
if (i !== taskStringLines.length - 1) {
await this.code.dispatchKeybinding('Enter');
}
}
await this.editors.saveOpenedFile();
}
}

View File

@@ -6,7 +6,6 @@
import { QuickInput } from './quickinput';
import { Code } from './code';
import { QuickAccess } from './quickaccess';
import { IElement } from './driver';
export enum Selector {
TerminalView = `#terminal`,
@@ -25,8 +24,7 @@ export enum Selector {
Tabs = '.tabs-list .monaco-list-row',
SplitButton = '.editor .codicon-split-horizontal',
XtermSplitIndex0 = '#terminal .terminal-groups-container .split-view-view:nth-child(1) .terminal-wrapper',
XtermSplitIndex1 = '#terminal .terminal-groups-container .split-view-view:nth-child(2) .terminal-wrapper',
Hide = '.hide'
XtermSplitIndex1 = '#terminal .terminal-groups-container .split-view-view:nth-child(2) .terminal-wrapper'
}
/**
@@ -38,8 +36,7 @@ export enum TerminalCommandIdWithValue {
ChangeIcon = 'workbench.action.terminal.changeIcon',
NewWithProfile = 'workbench.action.terminal.newWithProfile',
SelectDefaultProfile = 'workbench.action.terminal.selectDefaultShell',
AttachToSession = 'workbench.action.terminal.attachToSession',
WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal'
AttachToSession = 'workbench.action.terminal.attachToSession'
}
/**
@@ -78,30 +75,15 @@ export class Terminal {
constructor(private code: Code, private quickaccess: QuickAccess, private quickinput: QuickInput) { }
async runCommand(commandId: TerminalCommandId, expectedLocation?: 'editor' | 'panel'): Promise<void> {
async runCommand(commandId: TerminalCommandId): Promise<void> {
const keepOpen = commandId === TerminalCommandId.Join;
await this.quickaccess.runCommand(commandId, keepOpen);
if (keepOpen) {
await this.code.dispatchKeybinding('enter');
await this.quickinput.waitForQuickInputClosed();
}
switch (commandId) {
case TerminalCommandId.Show:
case TerminalCommandId.CreateNewEditor:
case TerminalCommandId.CreateNew:
case TerminalCommandId.NewWithProfile:
await this._waitForTerminal(expectedLocation === 'editor' || commandId === TerminalCommandId.CreateNewEditor ? 'editor' : 'panel');
break;
case TerminalCommandId.KillAll:
// HACK: Attempt to kill all terminals to clean things up, this is known to be flaky
// but the reason why isn't known. This is typically called in the after each hook,
// Since it's not actually required that all terminals are killed just continue on
// after 2 seconds.
await Promise.race([
this.code.waitForElements(Selector.Xterm, true, e => e.length === 0),
new Promise<void>(r => setTimeout(r, 2000))
]);
break;
if (commandId === TerminalCommandId.Show || commandId === TerminalCommandId.CreateNewEditor || commandId === TerminalCommandId.CreateNew || commandId === TerminalCommandId.NewWithProfile) {
return await this._waitForTerminal(commandId === TerminalCommandId.CreateNewEditor ? 'editor' : 'panel');
}
}
@@ -121,9 +103,6 @@ export class Terminal {
}
await this.code.dispatchKeybinding(altKey ? 'Alt+Enter' : 'enter');
await this.quickinput.waitForQuickInputClosed();
if (commandId === TerminalCommandIdWithValue.NewWithProfile) {
await this._waitForTerminal();
}
}
async runCommandInTerminal(commandText: string, skipEnter?: boolean): Promise<void> {
@@ -135,11 +114,11 @@ export class Terminal {
/**
* Creates a terminal using the new terminal command.
* @param expectedLocation The location to check the terminal for, defaults to panel.
* @param location The location to check the terminal for, defaults to panel.
*/
async createTerminal(expectedLocation?: 'editor' | 'panel'): Promise<void> {
await this.runCommand(TerminalCommandId.CreateNew, expectedLocation);
await this._waitForTerminal(expectedLocation);
async createTerminal(location?: 'editor' | 'panel'): Promise<void> {
await this.runCommand(TerminalCommandId.CreateNew);
await this._waitForTerminal(location);
}
async assertEditorGroupCount(count: number): Promise<void> {
@@ -162,11 +141,11 @@ export class Terminal {
let index = 0;
while (index < expectedCount) {
for (let groupIndex = 0; groupIndex < expectedGroups.length; groupIndex++) {
const terminalsInGroup = expectedGroups[groupIndex].length;
let terminalsInGroup = expectedGroups[groupIndex].length;
let indexInGroup = 0;
const isSplit = terminalsInGroup > 1;
while (indexInGroup < terminalsInGroup) {
const instance = expectedGroups[groupIndex][indexInGroup];
let instance = expectedGroups[groupIndex][indexInGroup];
const nameRegex = instance.name && isSplit ? new RegExp('\\s*[├┌└]\\s*' + instance.name) : instance.name ? new RegExp(/^\s*/ + instance.name) : undefined;
await this.assertTabExpected(undefined, index, nameRegex, instance.icon, instance.color, instance.description);
indexInGroup++;
@@ -176,16 +155,20 @@ export class Terminal {
}
}
async assertShellIntegrationActivated(): Promise<void> {
await this.waitForTerminalText(buffer => buffer.some(e => e.includes('Shell integration activated')));
}
async getTerminalGroups(): Promise<TerminalGroup[]> {
const tabCount = (await this.code.waitForElements(Selector.Tabs, true)).length;
const groups: TerminalGroup[] = [];
for (let i = 0; i < tabCount; i++) {
const title = await this.code.waitForElement(`${Selector.Tabs}[data-index="${i}"] ${Selector.TabsEntry}`, e => e?.textContent?.length ? e?.textContent?.length > 1 : false);
const description: IElement | undefined = await this.code.waitForElement(`${Selector.Tabs}[data-index="${i}"] ${Selector.TabsEntry} ${Selector.Description}`, () => true);
const description = await this.code.waitForElement(`${Selector.Tabs}[data-index="${i}"] ${Selector.TabsEntry} ${Selector.Description}`, e => e?.textContent?.length ? e?.textContent?.length > 1 : false);
const label: TerminalLabel = {
name: title.textContent.replace(/^[├┌└]\s*/, ''),
description: description?.textContent
description: description.textContent
};
// It's a new group if the the tab does not start with ├ or └
if (title.textContent.match(/^[├└]/)) {
@@ -234,18 +217,14 @@ export class Terminal {
await this.code.waitForElement(Selector.TerminalView, result => result === undefined);
}
async assertCommandDecorations(expectedCounts?: ICommandDecorationCounts, customIcon?: { updatedIcon: string; count: number }, showDecorations?: 'both' | 'gutter' | 'overviewRuler' | 'never'): Promise<void> {
async assertCommandDecorations(expectedCounts?: ICommandDecorationCounts, customConfig?: { updatedIcon: string; count: number }): Promise<void> {
if (expectedCounts) {
const placeholderSelector = showDecorations === 'overviewRuler' ? `${Selector.CommandDecorationPlaceholder}${Selector.Hide}` : Selector.CommandDecorationPlaceholder;
await this.code.waitForElements(placeholderSelector, true, decorations => decorations && decorations.length === expectedCounts.placeholder);
const successSelector = showDecorations === 'overviewRuler' ? `${Selector.CommandDecorationSuccess}${Selector.Hide}` : Selector.CommandDecorationSuccess;
await this.code.waitForElements(successSelector, true, decorations => decorations && decorations.length === expectedCounts.success);
const errorSelector = showDecorations === 'overviewRuler' ? `${Selector.CommandDecorationError}${Selector.Hide}` : Selector.CommandDecorationError;
await this.code.waitForElements(errorSelector, true, decorations => decorations && decorations.length === expectedCounts.error);
await this.code.waitForElements(Selector.CommandDecorationPlaceholder, true, decorations => decorations && decorations.length === expectedCounts.placeholder);
await this.code.waitForElements(Selector.CommandDecorationSuccess, true, decorations => decorations && decorations.length === expectedCounts.success);
await this.code.waitForElements(Selector.CommandDecorationError, true, decorations => decorations && decorations.length === expectedCounts.error);
}
if (customIcon) {
await this.code.waitForElements(`.terminal-command-decoration.codicon-${customIcon.updatedIcon}`, true, decorations => decorations && decorations.length === customIcon.count);
if (customConfig) {
await this.code.waitForElements(`.terminal-command-decoration.codicon-${customConfig.updatedIcon}`, true, decorations => decorations && decorations.length === customConfig.count);
}
}
@@ -282,10 +261,10 @@ export class Terminal {
/**
* Waits for the terminal to be focused and to contain content.
* @param expectedLocation The location to check the terminal for, defaults to panel.
* @param location The location to check the terminal for, defaults to panel.
*/
private async _waitForTerminal(expectedLocation?: 'editor' | 'panel'): Promise<void> {
private async _waitForTerminal(location?: 'editor' | 'panel'): Promise<void> {
await this.code.waitForElement(Selector.XtermFocused);
await this.code.waitForTerminalBuffer(expectedLocation === 'editor' ? Selector.XtermEditor : Selector.Xterm, lines => lines.some(line => line.length > 0));
await this.code.waitForTerminalBuffer(location === 'editor' ? Selector.XtermEditor : Selector.Xterm, lines => lines.some(line => line.length > 0));
}
}

View File

@@ -21,7 +21,6 @@ import { Code } from './code';
import { Terminal } from './terminal';
import { Notebook } from './notebook';
import { Localization } from './localization';
import { Task } from './task';
// {{SQL CARBON EDIT}}
import { ConnectionDialog } from './sql/connectionDialog';
@@ -60,7 +59,6 @@ export class Workbench {
readonly terminal: Terminal;
readonly notebook: Notebook;
readonly localization: Localization;
readonly task: Task;
// {{SQL CARBON EDIT}}
readonly connectionDialog: ConnectionDialog;
@@ -76,7 +74,7 @@ export class Workbench {
readonly taskPanel: TaskPanel;
// {{END}}
constructor(code: Code) {
constructor(code: Code, userDataPath: string) {
this.editors = new Editors(code);
this.quickinput = new QuickInput(code);
this.quickaccess = new QuickAccess(code, this.editors, this.quickinput);
@@ -89,7 +87,7 @@ export class Workbench {
this.debug = new Debug(code, this.quickaccess, this.editors, this.editor);
this.statusbar = new StatusBar(code);
this.problems = new Problems(code, this.quickaccess);
this.settingsEditor = new SettingsEditor(code, this.editors, this.editor, this.quickaccess);
this.settingsEditor = new SettingsEditor(code, userDataPath, this.editors, this.editor, this.quickaccess);
this.keybindingsEditor = new KeybindingsEditor(code);
this.terminal = new Terminal(code, this.quickaccess, this.quickinput);
// {{SQL CARBON EDIT}}
@@ -107,6 +105,5 @@ export class Workbench {
// {{END}}
this.notebook = new Notebook(this.quickaccess, this.quickinput, code);
this.localization = new Localization(code);
this.task = new Task(code, this.editor, this.editors, this.quickaccess, this.quickinput, this.terminal);
}
}