Merge branch 'main' into tyriar/120077

This commit is contained in:
Daniel Imms 2021-12-16 11:34:16 -08:00 committed by GitHub
commit 2584b60112
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
136 changed files with 1094 additions and 691 deletions

View file

@ -16,6 +16,7 @@
"eqeqeq": "warn",
"no-buffer-constructor": "warn",
"no-caller": "warn",
"no-case-declarations": "warn",
"no-debugger": "warn",
"no-duplicate-case": "warn",
"no-duplicate-imports": "warn",

View file

@ -219,6 +219,14 @@ steps:
timeoutInMinutes: 7
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \
yarn smoketest-no-compile --web --headless
timeoutInMinutes: 10
displayName: Run smoke tests (Browser, Chromium)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
@ -238,14 +246,6 @@ steps:
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \
yarn smoketest-no-compile --web --headless
timeoutInMinutes: 10
displayName: Run smoke tests (Browser, Chromium)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: PublishPipelineArtifact@0
inputs:
artifactName: crash-dump-macos-$(VSCODE_ARCH)

View file

@ -217,6 +217,14 @@ steps:
timeoutInMinutes: 7
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \
yarn smoketest-no-compile --web --headless --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader"
timeoutInMinutes: 10
displayName: Run smoke tests (Browser, Chromium)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
@ -234,14 +242,6 @@ steps:
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \
yarn smoketest-no-compile --web --headless --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader"
timeoutInMinutes: 10
displayName: Run smoke tests (Browser, Chromium)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: PublishPipelineArtifact@0
inputs:
artifactName: crash-dump-linux-$(VSCODE_ARCH)

View file

@ -206,6 +206,15 @@ steps:
displayName: Compile smoke tests
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --web --headless }
displayName: Run smoke tests (Browser, Chromium)
timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
@ -225,15 +234,6 @@ steps:
timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-web-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --web --headless }
displayName: Run smoke tests (Browser, Chromium)
timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
exec {.\build\azure-pipelines\win32\listprocesses.bat }

View file

@ -29,6 +29,7 @@ const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
// ignore: ['**/out/**', '**/node_modules/**']
// });
const compilations = [
'authentication-proxy/tsconfig.json',
'configuration-editing/build/tsconfig.json',
'configuration-editing/tsconfig.json',
'css-language-features/client/tsconfig.json',

View file

@ -223,6 +223,8 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
return true; // web: ship all extensions for now
}
// Skip shipping UI extensions because the client side will have them anyways
// and they'd just increase the download without being used
const manifest = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, extensionPath)).toString());
return !isUIExtension(manifest);
}).map((extensionPath) => path.basename(path.dirname(extensionPath)))

View file

@ -54,14 +54,14 @@
integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI=
"@types/node@14.x":
version "14.17.27"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.27.tgz#5054610d37bb5f6e21342d0e6d24c494231f3b85"
integrity sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==
version "14.18.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.0.tgz#98df2397f6936bfbff4f089e40e06fa5dd88d32a"
integrity sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ==
"@vscode/emmet-helper@^2.3.0":
version "2.8.2"
resolved "https://registry.yarnpkg.com/@vscode/emmet-helper/-/emmet-helper-2.8.2.tgz#9b2ce4fdd62cf3fda45cf8af67c012cfce55edc9"
integrity sha512-A/+pkBYQq2JTow1A2flfTmEOmiF780KpdkoX7VBjQ7wujeA+CFUPd17YdeIa9aim20+J5Jp7SFujPDwVFiQucQ==
version "2.8.3"
resolved "https://registry.yarnpkg.com/@vscode/emmet-helper/-/emmet-helper-2.8.3.tgz#f7c2b4a4751d03bcf2b421f0fce5b521a0f64a18"
integrity sha512-dkTSL+BaBBS8gFgPm/GMOU+XfxaMyI+Fl1IUYxEi8Iv24RfHf9/q2eCpV2hs7sncLcoKWEbMYe5gv4Ppmp2Oxw==
dependencies:
emmet "^2.3.0"
jsonc-parser "^2.3.0"
@ -71,9 +71,9 @@
vscode-uri "^2.1.2"
emmet@^2.3.0:
version "2.3.4"
resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.3.4.tgz#5ba0d7a5569a68c7697dfa890c772e4f3179d123"
integrity sha512-3IqSwmO+N2ZGeuhDyhV/TIOJFUbkChi53bcasSNRE7Yd+4eorbbYz4e53TpMECt38NtYkZNupQCZRlwdAYA42A==
version "2.3.5"
resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.3.5.tgz#7f80f9c3db6831d1ee2b458717b9c36a074b1a47"
integrity sha512-LcWfTamJnXIdMfLvJEC5Ld3hY5/KHXgv1L1bp6I7eEvB0ZhacHZ1kX0BYovJ8FroEsreLcq7n7kZhRMsf6jkXQ==
dependencies:
"@emmetio/abbreviation" "^2.2.2"
"@emmetio/css-abbreviation" "^2.1.4"
@ -103,9 +103,9 @@ queue@6.0.2:
inherits "~2.0.3"
vscode-languageserver-textdocument@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.2.tgz#2f9f6bd5b5eb3d8e21424c0c367009216f016236"
integrity sha512-T7uPC18+f8mYE4lbVZwb3OSmvwTZm3cuFhrdx9Bn2l11lmp3SvSuSVjy2JtvrghzjAo4G6Trqny2m9XGnFnWVA==
version "1.0.3"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.3.tgz#879f2649bfa5a6e07bc8b392c23ede2dfbf43eff"
integrity sha512-ynEGytvgTb6HVSUwPJIAZgiHQmPCx8bZ8w5um5Lz+q5DjP0Zj8wTFhQpyg8xaMvefDytw2+HH5yzqS+FhsR28A==
vscode-languageserver-types@^3.15.1:
version "3.16.0"

View file

@ -2821,7 +2821,7 @@ export class CommandCenter {
type = 'warning';
options.modal = false;
break;
case GitErrorCodes.AuthenticationFailed:
case GitErrorCodes.AuthenticationFailed: {
const regex = /Authentication failed for '(.*)'/i;
const match = regex.exec(err.stderr || String(err));
@ -2829,12 +2829,13 @@ export class CommandCenter {
? localize('auth failed specific', "Failed to authenticate to git remote:\n\n{0}", match[1])
: localize('auth failed', "Failed to authenticate to git remote.");
break;
}
case GitErrorCodes.NoUserNameConfigured:
case GitErrorCodes.NoUserEmailConfigured:
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");
choices.set(localize('learn more', "Learn More"), () => commands.executeCommand('vscode.open', Uri.parse('https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup')));
break;
default:
default: {
const hint = (err.stderr || err.message || String(err))
.replace(/^error: /mi, '')
.replace(/^> husky.*$/mi, '')
@ -2847,6 +2848,7 @@ export class CommandCenter {
: localize('git error', "Git error");
break;
}
}
if (!message) {

View file

@ -1196,7 +1196,7 @@ export class Repository {
break;
// Rename contains two paths, the second one is what the file is renamed/copied to.
case 'R':
case 'R': {
if (index >= entries.length) {
break;
}
@ -1215,7 +1215,7 @@ export class Repository {
});
continue;
}
default:
// Unknown status
break entriesLoop;

View file

@ -664,7 +664,7 @@ class ResourceCommandResolver {
case Status.MODIFIED:
case Status.UNTRACKED:
case Status.IGNORED:
case Status.INTENT_TO_ADD:
case Status.INTENT_TO_ADD: {
const uriString = resource.resourceUri.toString();
const [indexStatus] = this.repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
@ -673,7 +673,7 @@ class ResourceCommandResolver {
}
return resource.resourceUri;
}
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return resource.resourceUri;

View file

@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Uri } from 'vscode';
const VALID_DESKTOP_CALLBACK_SCHEMES = [
'vscode',
'vscode-insiders',
'code-oss',
'vscode-wsl',
'vscode-exploration'
];
// This comes from the GitHub Authentication server
export function isSupportedEnvironment(url: Uri): boolean {
return VALID_DESKTOP_CALLBACK_SCHEMES.includes(url.scheme) || url.authority.endsWith('vscode.dev') || url.authority.endsWith('github.dev');
}

View file

@ -43,7 +43,11 @@ export class GitHubAuthenticationProvider implements vscode.AuthenticationProvid
this._telemetryReporter = new ExperimentationTelemetry(context, new TelemetryReporter(name, version, aiKey));
if (this.type === AuthProviderType.github) {
this._githubServer = new GitHubServer(this._logger, this._telemetryReporter);
this._githubServer = new GitHubServer(
// We only can use the Device Code flow when we are running with a remote extension host.
context.extension.extensionKind === vscode.ExtensionKind.Workspace,
this._logger,
this._telemetryReporter);
} else {
this._githubServer = new GitHubEnterpriseServer(this._logger, this._telemetryReporter);
}
@ -216,7 +220,7 @@ export class GitHubAuthenticationProvider implements vscode.AuthenticationProvid
return session;
} catch (e) {
// If login was cancelled, do not notify user.
if (e === 'Cancelled') {
if (e === 'Cancelled' || e.message === 'Cancelled') {
/* __GDPR__
"loginCancelled" : { }
*/

View file

@ -11,8 +11,10 @@ import { PromiseAdapter, promiseFromEvent } from './common/utils';
import { ExperimentationTelemetry } from './experimentationService';
import { AuthProviderType } from './github';
import { Log } from './common/logger';
import { isSupportedEnvironment } from './common/env';
const localize = nls.loadMessageBundle();
const CLIENT_ID = '01ab8ac9400c4e429b23';
const NETWORK_ERROR = 'network error';
const AUTH_RELAY_SERVER = 'vscode-auth.github.com';
@ -45,6 +47,13 @@ export interface IGitHubServer extends vscode.Disposable {
type: AuthProviderType;
}
interface IGitHubDeviceCodeResponse {
device_code: string;
user_code: string;
verification_uri: string;
interval: number;
}
async function getScopes(token: string, serverUri: vscode.Uri, logger: Log): Promise<string[]> {
try {
logger.info('Getting token scopes...');
@ -105,7 +114,7 @@ export class GitHubServer implements IGitHubServer {
private _disposable: vscode.Disposable;
private _uriHandler = new UriEventHandler(this._logger);
constructor(private readonly _logger: Log, private readonly _telemetryReporter: ExperimentationTelemetry) {
constructor(private readonly _supportDeviceCodeFlow: boolean, private readonly _logger: Log, private readonly _telemetryReporter: ExperimentationTelemetry) {
this._disposable = vscode.Disposable.from(
vscode.commands.registerCommand(this._statusBarCommandId, () => this.manuallyProvideUri()),
vscode.window.registerUriHandler(this._uriHandler));
@ -115,10 +124,6 @@ export class GitHubServer implements IGitHubServer {
this._disposable.dispose();
}
private isTestEnvironment(url: vscode.Uri): boolean {
return /\.azurewebsites\.net$/.test(url.authority) || url.authority.startsWith('localhost:');
}
// TODO@joaomoreno TODO@TylerLeonhardt
private async isNoCorsEnvironment(): Promise<boolean> {
const uri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/dummy`));
@ -130,9 +135,12 @@ export class GitHubServer implements IGitHubServer {
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`));
if (this.isTestEnvironment(callbackUri)) {
const token = await vscode.window.showInputBox({ prompt: 'GitHub Personal Access Token', ignoreFocusOut: true });
if (!token) { throw new Error('Sign in failed: No token provided'); }
if (!isSupportedEnvironment(callbackUri)) {
const token = this._supportDeviceCodeFlow
? await this.doDeviceCodeFlow(scopes)
: await vscode.window.showInputBox({ prompt: 'GitHub Personal Access Token', ignoreFocusOut: true });
if (!token) { throw new Error('No token provided'); }
const tokenScopes = await getScopes(token, this.getServerUri('/'), this._logger); // Example: ['repo', 'user']
const scopesList = scopes.split(' '); // Example: 'read:user repo user:email'
@ -187,6 +195,96 @@ export class GitHubServer implements IGitHubServer {
});
}
private async doDeviceCodeFlow(scopes: string): Promise<string> {
// Get initial device code
const uri = `https://github.com/login/device/code?client_id=${CLIENT_ID}&scope=${scopes}`;
const result = await fetch(uri, {
method: 'POST',
headers: {
Accept: 'application/json'
}
});
if (!result.ok) {
throw new Error(`Failed to get one-time code: ${await result.text()}`);
}
const json = await result.json() as IGitHubDeviceCodeResponse;
await vscode.env.clipboard.writeText(json.user_code);
const modalResult = await vscode.window.showInformationMessage(
localize('code.title', "Your Code: {0}", json.user_code),
{
modal: true,
detail: localize('code.detail', "The above one-time code has been copied to your clipboard. To finish authenticating, paste it on GitHub.")
}, 'Continue to GitHub');
if (modalResult !== 'Continue to GitHub') {
throw new Error('Cancelled');
}
const uriToOpen = await vscode.env.asExternalUri(vscode.Uri.parse(json.verification_uri));
await vscode.env.openExternal(uriToOpen);
return await vscode.window.withProgress<string>({
location: vscode.ProgressLocation.Notification,
cancellable: true,
title: localize(
'progress',
"Open [{0}]({0}) in a new tab and paste your one-time code: {1}",
json.verification_uri,
json.user_code)
}, async (_, token) => {
return await this.waitForDeviceCodeAccessToken(json, token);
});
}
private async waitForDeviceCodeAccessToken(
json: IGitHubDeviceCodeResponse,
token: vscode.CancellationToken
): Promise<string> {
const refreshTokenUri = `https://github.com/login/oauth/access_token?client_id=${CLIENT_ID}&device_code=${json.device_code}&grant_type=urn:ietf:params:oauth:grant-type:device_code`;
// Try for 2 minutes
const attempts = 120 / json.interval;
for (let i = 0; i < attempts; i++) {
await new Promise(resolve => setTimeout(resolve, json.interval * 1000));
if (token.isCancellationRequested) {
throw new Error('Cancelled');
}
let accessTokenResult;
try {
accessTokenResult = await fetch(refreshTokenUri, {
method: 'POST',
headers: {
Accept: 'application/json'
}
});
} catch {
continue;
}
if (!accessTokenResult.ok) {
continue;
}
const accessTokenJson = await accessTokenResult.json();
if (accessTokenJson.error === 'authorization_pending') {
continue;
}
if (accessTokenJson.error) {
throw new Error(accessTokenJson.error_description);
}
return accessTokenJson.access_token;
}
throw new Error('Cancelled');
}
private exchangeCodeForToken: (scopes: string) => PromiseAdapter<vscode.Uri, string> =
(scopes) => async (uri, resolve, reject) => {
const query = parseQuery(uri);

View file

@ -126,14 +126,14 @@
"explorer/context": [
{
"command": "markdown.showPreview",
"when": "resourceLangId == markdown",
"when": "resourceLangId == markdown && !hasCustomMarkdownPreview",
"group": "navigation"
}
],
"editor/title/context": [
{
"command": "markdown.showPreview",
"when": "resourceLangId == markdown",
"when": "resourceLangId == markdown && !hasCustomMarkdownPreview",
"group": "1_open"
}
],

View file

@ -124,7 +124,7 @@ window.addEventListener('message', async event => {
}
return;
case 'updateContent':
case 'updateContent': {
const root = document.querySelector('.markdown-body')!;
const parser = new DOMParser();
@ -216,6 +216,7 @@ window.addEventListener('message', async event => {
window.dispatchEvent(new CustomEvent('vscode.markdown.updateContent'));
break;
}
}
}, false);

View file

@ -120,7 +120,7 @@ export function createServer(nonce: string) {
const server = http.createServer(function (req, res) {
const reqUrl = url.parse(req.url!, /* parseQueryString */ true);
switch (reqUrl.pathname) {
case '/signin':
case '/signin': {
const receivedNonce = ((reqUrl.query.nonce as string) || '').replace(/ /g, '+');
if (receivedNonce === nonce) {
deferredRedirect.resolve({ req, res });
@ -129,6 +129,7 @@ export function createServer(nonce: string) {
deferredRedirect.resolve({ err, res });
}
break;
}
case '/':
sendFile(res, path.join(__dirname, '../media/auth.html'), 'text/html; charset=utf-8');
break;

View file

@ -69,11 +69,12 @@ export class TypeScriptReferencesCodeLensProvider extends TypeScriptBaseCodeLens
}
switch (item.kind) {
case PConst.Kind.function:
case PConst.Kind.function: {
const showOnAllFunctions = vscode.workspace.getConfiguration(this.modeId).get<boolean>('referencesCodeLens.showOnAllFunctions');
if (showOnAllFunctions) {
return getSymbolRange(document, item);
}
}
// fallthrough
case PConst.Kind.const:

View file

@ -816,10 +816,10 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider<
case '#': // Workaround for https://github.com/microsoft/TypeScript/issues/36367
return this.client.apiVersion.lt(API.v381) ? undefined : '#';
case ' ':
case ' ': {
const space: Proto.CompletionsTriggerCharacter = ' ';
return this.client.apiVersion.gte(API.v430) ? space : undefined;
}
case '.':
case '"':
case '\'':

View file

@ -167,7 +167,7 @@ class BufferSynchronizer {
private updatePending(resource: vscode.Uri, op: BufferOperation): boolean {
switch (op.type) {
case BufferOperationType.Close:
case BufferOperationType.Close: {
const existing = this._pending.get(resource);
switch (existing?.type) {
case BufferOperationType.Open:
@ -175,6 +175,7 @@ class BufferSynchronizer {
return false; // Open then close. No need to do anything
}
break;
}
}
if (this._pending.has(resource)) {

View file

@ -148,7 +148,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
}
break;
case 'event':
case 'event': {
const event = message as Proto.Event;
if (event.event === 'requestCompleted') {
const seq = (event as Proto.RequestCompletedEvent).body.request_seq;
@ -162,7 +162,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
this._onEvent.fire(event);
}
break;
}
default:
throw new Error(`Unknown message type ${message.type} received`);
}

View file

@ -866,7 +866,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
switch (event.event) {
case EventName.syntaxDiag:
case EventName.semanticDiag:
case EventName.suggestionDiag:
case EventName.suggestionDiag: {
// This event also roughly signals that projects have been loaded successfully (since the TS server is synchronous)
this.loadingIndicator.reset();
@ -879,34 +879,32 @@ export default class TypeScriptServiceClient extends Disposable implements IType
});
}
break;
}
case EventName.configFileDiag:
this._onConfigDiagnosticsReceived.fire(event as Proto.ConfigFileDiagnosticEvent);
break;
case EventName.telemetry:
{
const body = (event as Proto.TelemetryEvent).body;
this.dispatchTelemetryEvent(body);
break;
case EventName.telemetry: {
const body = (event as Proto.TelemetryEvent).body;
this.dispatchTelemetryEvent(body);
break;
}
case EventName.projectLanguageServiceState: {
const body = (event as Proto.ProjectLanguageServiceStateEvent).body!;
if (this.serverState.type === ServerState.Type.Running) {
this.serverState.updateLanguageServiceEnabled(body.languageServiceEnabled);
}
case EventName.projectLanguageServiceState:
{
const body = (event as Proto.ProjectLanguageServiceStateEvent).body!;
if (this.serverState.type === ServerState.Type.Running) {
this.serverState.updateLanguageServiceEnabled(body.languageServiceEnabled);
}
this._onProjectLanguageServiceStateChanged.fire(body);
break;
}
case EventName.projectsUpdatedInBackground:
this._onProjectLanguageServiceStateChanged.fire(body);
break;
}
case EventName.projectsUpdatedInBackground: {
this.loadingIndicator.reset();
const body = (event as Proto.ProjectsUpdatedInBackgroundEvent).body;
const resources = body.openFiles.map(file => this.toResource(file));
this.bufferSyncSupport.getErr(resources);
break;
}
case EventName.beginInstallTypes:
this._onDidBeginInstallTypings.fire((event as Proto.BeginInstallTypesEvent).body);
break;
@ -936,7 +934,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
private dispatchTelemetryEvent(telemetryData: Proto.TelemetryEventBody): void {
const properties: { [key: string]: string } = Object.create(null);
switch (telemetryData.telemetryEventName) {
case 'typingsInstalled':
case 'typingsInstalled': {
const typingsInstalledPayload: Proto.TypingsInstalledTelemetryEventPayload = (telemetryData.payload as Proto.TypingsInstalledTelemetryEventPayload);
properties['installedPackages'] = typingsInstalledPayload.installedPackages;
@ -947,8 +945,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType
properties['typingsInstallerVersion'] = typingsInstalledPayload.typingsInstallerVersion;
}
break;
default:
}
default: {
const payload = telemetryData.payload;
if (payload) {
Object.keys(payload).forEach((key) => {
@ -962,6 +960,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
});
}
break;
}
}
if (telemetryData.telemetryEventName === 'projectInfo') {
if (this.serverState.type === ServerState.Type.Running) {

View file

@ -49,7 +49,7 @@ function getTagBodyText(
const text = convertLinkTags(tag.text, filePathConverter);
switch (tag.name) {
case 'example':
case 'example': {
// check for caption tags, fix for #79704
const captionTagMatches = text.match(/<caption>(.*?)<\/caption>\s*(\r\n|\n)/);
if (captionTagMatches && captionTagMatches.index === 0) {
@ -57,7 +57,8 @@ function getTagBodyText(
} else {
return makeCodeblock(text);
}
case 'author':
}
case 'author': {
// fix obsucated email address, #80898
const emailMatch = text.match(/(.+)\s<([-.\w]+@[-.\w]+)>/);
@ -66,6 +67,7 @@ function getTagBodyText(
} else {
return `${emailMatch[1]} ${emailMatch[2]}`;
}
}
case 'default':
return makeCodeblock(text);
}
@ -81,7 +83,7 @@ function getTagDocumentation(
case 'augments':
case 'extends':
case 'param':
case 'template':
case 'template': {
const body = (convertLinkTags(tag.text, filePathConverter)).split(/^(\S+)\s*-?\s*/);
if (body?.length === 3) {
const param = body[1];
@ -92,6 +94,7 @@ function getTagDocumentation(
}
return label + (doc.match(/\r\n|\n/g) ? ' \n' + processInlineTags(doc) : ` \u2014 ${processInlineTags(doc)}`);
}
}
}
// Generic tag

View file

@ -981,7 +981,7 @@ suite('vscode API - workspace', () => {
assert.strictEqual(document.getText(), expected);
});
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867', async function () {
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867, 1/3', async function () {
const file1 = await createRandomFile();
const file2 = await createRandomFile();
@ -1008,7 +1008,7 @@ suite('vscode API - workspace', () => {
assert.strictEqual(e.files[1].oldUri.toString(), file2.toString());
});
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867', async function () {
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867, 2/3', async function () {
const event = new Promise<vscode.FileWillCreateEvent>(resolve => {
let sub = vscode.workspace.onWillCreateFiles(e => {
@ -1032,7 +1032,7 @@ suite('vscode API - workspace', () => {
assert.strictEqual(e.files[1].toString(), file2.toString());
});
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867', async function () {
test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867, 3/3', async function () {
const file1 = await createRandomFile();
const file2 = await createRandomFile();

View file

@ -5,11 +5,12 @@
import * as assert from 'assert';
import { EOL } from 'os';
import * as crypto from 'crypto';
import * as vscode from 'vscode';
import { TestFS } from './memfs';
export function rndName() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
return crypto.randomBytes(8).toString('hex');
}
export const testFs = new TestFS('fake-fs', true);

View file

@ -60,7 +60,7 @@
},
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
"@parcel/watcher": "2.0.4",
"@parcel/watcher": "2.0.5",
"@vscode/sqlite3": "4.0.12",
"@vscode/sudo-prompt": "9.3.1",
"@vscode/vscode-languagedetection": "1.0.21",

View file

@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
"@parcel/watcher": "2.0.4",
"@parcel/watcher": "2.0.5",
"@vscode/vscode-languagedetection": "1.0.21",
"applicationinsights": "1.4.2",
"cookie": "^0.4.0",

View file

@ -83,10 +83,10 @@
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.4.tgz#40e1c0ad20743fcee1604a7df2c57faf0aa1af87"
integrity sha512-Ot53G927ykMF8cQ3/zq4foZtdk+Tt1YpX7aUTHxBU7UHNdkEiBvBfZSq+rnlUmKCJ19VatwPG4mNzvcGpBj4og==
"@parcel/watcher@2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b"
integrity sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==
"@parcel/watcher@2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.5.tgz#f913a54e1601b0aac972803829b0eece48de215b"
integrity sha512-x0hUbjv891omnkcHD7ZOhiyyUqUUR6MNjq89JhEI3BxppeKWAm6NPQsqqRrAkCJBogdT/o/My21sXtTI9rJIsw==
dependencies:
node-addon-api "^3.2.1"
node-gyp-build "^4.3.0"

View file

@ -215,6 +215,23 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
dom.EventHelper.stop(e);
}));
// Intercept touch events
// The following implementation is slightly different from the mouse event handlers above.
// Use the following helper variable, otherwise the list flickers.
let listIsVisibleOnTouchStart: boolean;
this._register(dom.addDisposableListener(this.selectElement, 'touchstart', (e) => {
listIsVisibleOnTouchStart = this._isVisible;
}));
this._register(dom.addDisposableListener(this.selectElement, 'touchend', (e) => {
dom.EventHelper.stop(e);
if (listIsVisibleOnTouchStart) {
this.hideSelectDropDown(true);
} else {
this.showSelectDropDown();
}
}));
// Intercept keyboard handling
this._register(dom.addDisposableListener(this.selectElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
@ -761,10 +778,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
// SetUp list mouse controller - control navigation, disabled items, focus
const onMouseUp = this._register(new DomEmitter(this.selectList.getHTMLElement(), 'mouseup'));
this._register(Event.chain(onMouseUp.event)
.filter(() => this.selectList.length > 0)
.on(e => this.onMouseUp(e), this));
this._register(dom.addDisposableListener(this.selectList.getHTMLElement(), dom.EventType.POINTER_DOWN, e => this.onPointerDown(e)));
this._register(this.selectList.onMouseOver(e => typeof e.index !== 'undefined' && this.selectList.setFocus([e.index])));
this._register(this.selectList.onDidChangeFocus(e => this.onListFocus(e)));
@ -785,7 +799,12 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
// List methods
// List mouse controller - active exit, select option, fire onDidSelect if change, return focus to parent select
private onMouseUp(e: MouseEvent): void {
// Also takes in touchend events
private onPointerDown(e: PointerEvent): void {
if (!this.selectList.length) {
return;
}
dom.EventHelper.stop(e);

View file

@ -177,7 +177,7 @@ function parseRegExp(pattern: string): string {
inBrackets = true;
continue;
case '}':
case '}': {
const choices = splitGlobAware(braceVal, ',');
// Converts {foo,bar} => [foo|bar]
@ -189,7 +189,7 @@ function parseRegExp(pattern: string): string {
braceVal = '';
break;
}
case ']':
regEx += ('[' + bracketVal + ']');

View file

@ -332,7 +332,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
case CharacterCodes.t:
result += '\t';
break;
case CharacterCodes.u:
case CharacterCodes.u: {
const ch3 = scanHexDigits(4);
if (ch3 >= 0) {
result += String.fromCharCode(ch3);
@ -340,6 +340,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
scanError = ScanError.InvalidUnicode;
}
break;
}
default:
scanError = ScanError.InvalidEscapeCharacter;
}
@ -425,7 +426,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
return token = SyntaxKind.StringLiteral;
// comments
case CharacterCodes.slash:
case CharacterCodes.slash: {
const start = pos - 1;
// Single-line comment
if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
@ -471,7 +472,7 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
value += String.fromCharCode(code);
pos++;
return token = SyntaxKind.Unknown;
}
// numbers
case CharacterCodes.minus:
value += String.fromCharCode(code);
@ -1016,7 +1017,7 @@ export function getNodeValue(node: Node): any {
switch (node.type) {
case 'array':
return node.children!.map(getNodeValue);
case 'object':
case 'object': {
const obj = Object.create(null);
for (let prop of node.children!) {
const valueNode = prop.children![1];
@ -1025,6 +1026,7 @@ export function getNodeValue(node: Node): any {
}
}
return obj;
}
case 'null':
case 'string':
case 'number':
@ -1162,7 +1164,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions
function parseLiteral(): boolean {
switch (_scanner.getToken()) {
case SyntaxKind.NumericLiteral:
case SyntaxKind.NumericLiteral: {
let value = 0;
try {
value = JSON.parse(_scanner.getTokenValue());
@ -1175,6 +1177,7 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions
}
onLiteralValue(value);
break;
}
case SyntaxKind.NullKeyword:
onLiteralValue(null);
break;

View file

@ -119,10 +119,11 @@ export function guessMimeTypes(resource: URI | null, firstLine?: string): string
case Schemas.file:
path = resource.fsPath;
break;
case Schemas.data:
case Schemas.data: {
const metadata = DataUri.parseMetaData(resource);
path = metadata.get(DataUri.META_DATA_LABEL);
break;
}
default:
path = resource.path;
}

View file

@ -565,14 +565,14 @@ export class ChannelClient implements IChannelClient, IDisposable {
c(response.data);
break;
case ResponseType.PromiseError:
case ResponseType.PromiseError: {
this.handlers.delete(id);
const error = new Error(response.data.message);
(<any>error).stack = response.data.stack;
error.name = response.data.name;
e(error);
break;
}
case ResponseType.PromiseErrorObj:
this.handlers.delete(id);
e(response.data);

View file

@ -303,18 +303,20 @@ export class QuickInputList {
this.list.setFocus(range(this.list.length));
}
break;
case KeyCode.UpArrow:
case KeyCode.UpArrow: {
const focus1 = this.list.getFocus();
if (focus1.length === 1 && focus1[0] === 0) {
this._onLeave.fire();
}
break;
case KeyCode.DownArrow:
}
case KeyCode.DownArrow: {
const focus2 = this.list.getFocus();
if (focus2.length === 1 && focus2[0] === this.list.length - 1) {
this._onLeave.fire();
}
break;
}
}
this._onKeyDown.fire(event);

View file

@ -10,7 +10,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
import { IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition, createCoordinatesRelativeToEditor } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { Position } from 'vs/editor/common/core/position';
@ -172,7 +172,8 @@ export class MouseHandler extends ViewEventHandler {
return null;
}
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, null);
const relativePos = createCoordinatesRelativeToEditor(this.viewHelper.viewDomNode, editorPos, pos);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, relativePos, null);
}
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): IMouseTarget {
@ -185,11 +186,11 @@ export class MouseHandler extends ViewEventHandler {
);
}
}
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, testEventTarget ? target : null);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, e.relativePos, testEventTarget ? target : null);
}
private _getMouseColumn(e: EditorMouseEvent): number {
return this.mouseTargetFactory.getMouseColumn(e.editorPos, e.pos);
return this.mouseTargetFactory.getMouseColumn(e.relativePos);
}
protected _onContextMenu(e: EditorMouseEvent, testEventTarget: boolean): void {
@ -476,7 +477,7 @@ class MouseDownOperation extends Disposable {
}
if (e.posy > editorContent.y + editorContent.height) {
const verticalOffset = viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y);
const verticalOffset = viewLayout.getCurrentScrollTop() + e.relativePos.y;
const viewZoneData = HitTestContext.getZoneAtCoord(this._context, verticalOffset);
if (viewZoneData) {
const newPosition = this._helpPositionJumpOverViewZone(viewZoneData);
@ -489,7 +490,7 @@ class MouseDownOperation extends Disposable {
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber)));
}
const possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y));
const possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + e.relativePos.y);
if (e.posx < editorContent.x) {
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, 1));

View file

@ -5,7 +5,7 @@
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorPagePosition, PageCoordinates } from 'vs/editor/browser/editorDom';
import { ClientCoordinates, EditorMouseEvent, EditorPagePosition, PageCoordinates, CoordinatesRelativeToEditor } from 'vs/editor/browser/editorDom';
import { PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
@ -374,6 +374,7 @@ abstract class BareHitTestRequest {
public readonly editorPos: EditorPagePosition;
public readonly pos: PageCoordinates;
public readonly relativePos: CoordinatesRelativeToEditor;
public readonly mouseVerticalOffset: number;
public readonly isInMarginArea: boolean;
public readonly isInContentArea: boolean;
@ -381,13 +382,14 @@ abstract class BareHitTestRequest {
protected readonly mouseColumn: number;
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates) {
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor) {
this.editorPos = editorPos;
this.pos = pos;
this.relativePos = relativePos;
this.mouseVerticalOffset = Math.max(0, ctx.getCurrentScrollTop() + pos.y - editorPos.y);
this.mouseContentHorizontalOffset = ctx.getCurrentScrollLeft() + pos.x - editorPos.x - ctx.layoutInfo.contentLeft;
this.isInMarginArea = (pos.x - editorPos.x < ctx.layoutInfo.contentLeft && pos.x - editorPos.x >= ctx.layoutInfo.glyphMarginLeft);
this.mouseVerticalOffset = Math.max(0, ctx.getCurrentScrollTop() + this.relativePos.y);
this.mouseContentHorizontalOffset = ctx.getCurrentScrollLeft() + this.relativePos.x - ctx.layoutInfo.contentLeft;
this.isInMarginArea = (this.relativePos.x < ctx.layoutInfo.contentLeft && this.relativePos.x >= ctx.layoutInfo.glyphMarginLeft);
this.isInContentArea = !this.isInMarginArea;
this.mouseColumn = Math.max(0, MouseTargetFactory._getMouseColumn(this.mouseContentHorizontalOffset, ctx.typicalHalfwidthCharacterWidth));
}
@ -398,8 +400,8 @@ class HitTestRequest extends BareHitTestRequest {
public readonly target: Element | null;
public readonly targetPath: Uint8Array;
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, target: Element | null) {
super(ctx, editorPos, pos);
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor, target: Element | null) {
super(ctx, editorPos, pos, relativePos);
this._ctx = ctx;
if (target) {
@ -412,7 +414,7 @@ class HitTestRequest extends BareHitTestRequest {
}
public override toString(): string {
return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? (<HTMLElement>this.target).outerHTML : null}`;
return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), relativePos(${this.relativePos.x},${this.relativePos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? (<HTMLElement>this.target).outerHTML : null}`;
}
public fulfill(type: MouseTargetType.UNKNOWN, position?: Position | null, range?: EditorRange | null): MouseTarget;
@ -436,7 +438,7 @@ class HitTestRequest extends BareHitTestRequest {
}
public withTarget(target: Element | null): HitTestRequest {
return new HitTestRequest(this._ctx, this.editorPos, this.pos, target);
return new HitTestRequest(this._ctx, this.editorPos, this.pos, this.relativePos, target);
}
}
@ -480,9 +482,9 @@ export class MouseTargetFactory {
return false;
}
public createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
public createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastRenderData);
const request = new HitTestRequest(ctx, editorPos, pos, target);
const request = new HitTestRequest(ctx, editorPos, pos, relativePos, target);
try {
const r = MouseTargetFactory._createMouseTarget(ctx, request, false);
// console.log(r.toString());
@ -632,7 +634,7 @@ export class MouseTargetFactory {
if (request.isInMarginArea) {
const res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset);
const pos = res.range.getStartPosition();
let offset = Math.abs(request.pos.x - request.editorPos.x);
let offset = Math.abs(request.relativePos.x);
const detail: IMarginData = {
isAfterLines: res.isAfterLines,
glyphMarginLeft: ctx.layoutInfo.glyphMarginLeft,
@ -745,10 +747,10 @@ export class MouseTargetFactory {
return null;
}
public getMouseColumn(editorPos: EditorPagePosition, pos: PageCoordinates): number {
public getMouseColumn(relativePos: CoordinatesRelativeToEditor): number {
const options = this._context.configuration.options;
const layoutInfo = options.get(EditorOption.layoutInfo);
const mouseContentHorizontalOffset = this._context.viewLayout.getCurrentScrollLeft() + pos.x - editorPos.x - layoutInfo.contentLeft;
const mouseContentHorizontalOffset = this._context.viewLayout.getCurrentScrollLeft() + relativePos.x - layoutInfo.contentLeft;
return MouseTargetFactory._getMouseColumn(mouseContentHorizontalOffset, options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth);
}
@ -834,8 +836,8 @@ export class MouseTargetFactory {
if (adjustedPageY <= request.editorPos.y) {
adjustedPageY = request.editorPos.y + 1;
}
if (adjustedPageY >= request.editorPos.y + ctx.layoutInfo.height) {
adjustedPageY = request.editorPos.y + ctx.layoutInfo.height - 1;
if (adjustedPageY >= request.editorPos.y + request.editorPos.height) {
adjustedPageY = request.editorPos.y + request.editorPos.height - 1;
}
const adjustedPage = new PageCoordinates(request.pos.x, adjustedPageY);

View file

@ -62,11 +62,45 @@ export class EditorPagePosition {
) { }
}
/**
* Coordinates relative to the the (top;left) of the editor that can be used safely with other internal editor metrics.
* **NOTE**: This position is obtained by taking page coordinates and transforming them relative to the
* editor's (top;left) position in a way in which scale transformations are taken into account.
* **NOTE**: These coordinates could be negative if the mouse position is outside the editor.
*/
export class CoordinatesRelativeToEditor {
_positionRelativeToEditorBrand: void = undefined;
constructor(
public readonly x: number,
public readonly y: number
) { }
}
export function createEditorPagePosition(editorViewDomNode: HTMLElement): EditorPagePosition {
const editorPos = dom.getDomNodePagePosition(editorViewDomNode);
return new EditorPagePosition(editorPos.left, editorPos.top, editorPos.width, editorPos.height);
}
export function createCoordinatesRelativeToEditor(editorViewDomNode: HTMLElement, editorPagePosition: EditorPagePosition, pos: PageCoordinates) {
// The editor's page position is read from the DOM using getBoundingClientRect().
//
// getBoundingClientRect() returns the actual dimensions, while offsetWidth and offsetHeight
// reflect the unscaled size. We can use this difference to detect a transform:scale()
// and we will apply the transformation in inverse to get mouse coordinates that make sense inside the editor.
//
// This could be expanded to cover rotation as well maybe by walking the DOM up from `editorViewDomNode`
// and computing the effective transformation matrix using getComputedStyle(element).transform.
//
const scaleX = editorPagePosition.width / editorViewDomNode.offsetWidth;
const scaleY = editorPagePosition.height / editorViewDomNode.offsetHeight;
// Adjust mouse offsets if editor appears to be scaled via transforms
const relativeX = (pos.x - editorPagePosition.x) / scaleX;
const relativeY = (pos.y - editorPagePosition.y) / scaleY;
return new CoordinatesRelativeToEditor(relativeX, relativeY);
}
export class EditorMouseEvent extends StandardMouseEvent {
_editorMouseEventBrand: void = undefined;
@ -80,10 +114,18 @@ export class EditorMouseEvent extends StandardMouseEvent {
*/
public readonly editorPos: EditorPagePosition;
/**
* Coordinates relative to the (top;left) of the editor.
* *NOTE*: These coordinates are preferred because they take into account transformations applied to the editor.
* *NOTE*: These coordinates could be negative if the mouse position is outside the editor.
*/
public readonly relativePos: CoordinatesRelativeToEditor;
constructor(e: MouseEvent, editorViewDomNode: HTMLElement) {
super(e);
this.pos = new PageCoordinates(this.posx, this.posy);
this.editorPos = createEditorPagePosition(editorViewDomNode);
this.relativePos = createCoordinatesRelativeToEditor(editorViewDomNode, this.editorPos, this.pos);
}
}

View file

@ -69,7 +69,7 @@ export class RangeUtil {
return result;
}
private static _createHorizontalRangesFromClientRects(clientRects: DOMRectList | null, clientRectDeltaLeft: number): FloatHorizontalRange[] | null {
private static _createHorizontalRangesFromClientRects(clientRects: DOMRectList | null, clientRectDeltaLeft: number, clientRectScale: number): FloatHorizontalRange[] | null {
if (!clientRects || clientRects.length === 0) {
return null;
}
@ -80,13 +80,13 @@ export class RangeUtil {
const result: FloatHorizontalRange[] = [];
for (let i = 0, len = clientRects.length; i < len; i++) {
const clientRect = clientRects[i];
result[i] = new FloatHorizontalRange(Math.max(0, clientRect.left - clientRectDeltaLeft), clientRect.width);
result[i] = new FloatHorizontalRange(Math.max(0, (clientRect.left - clientRectDeltaLeft) / clientRectScale), clientRect.width / clientRectScale);
}
return this._mergeAdjacentRanges(result);
}
public static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, endNode: HTMLElement): FloatHorizontalRange[] | null {
public static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, clientRectScale: number, endNode: HTMLElement): FloatHorizontalRange[] | null {
// Panic check
const min = 0;
const max = domNode.children.length - 1;
@ -100,7 +100,7 @@ export class RangeUtil {
// We must find the position at the beginning of a <span>
// To cover cases of empty <span>s, avoid using a range and use the <span>'s bounding box
const clientRects = domNode.children[startChildIndex].getClientRects();
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale);
}
// If crossing over to a span only to select offset 0, then use the previous span's maximum offset
@ -135,6 +135,6 @@ export class RangeUtil {
endOffset = Math.min(endElement.textContent!.length, Math.max(0, endOffset));
const clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale);
}
}

View file

@ -48,21 +48,39 @@ export class DomReadingContext {
private readonly _domNode: HTMLElement;
private _clientRectDeltaLeft: number;
private _clientRectDeltaLeftRead: boolean;
private _clientRectScale: number;
private _clientRectRead: boolean;
private readClientRect(): void {
if (!this._clientRectRead) {
this._clientRectRead = true;
const rect = this._domNode.getBoundingClientRect();
this._clientRectDeltaLeft = rect.left;
this._clientRectScale = rect.width / this._domNode.offsetWidth;
}
}
public get clientRectDeltaLeft(): number {
if (!this._clientRectDeltaLeftRead) {
this._clientRectDeltaLeftRead = true;
this._clientRectDeltaLeft = this._domNode.getBoundingClientRect().left;
if (!this._clientRectRead) {
this.readClientRect();
}
return this._clientRectDeltaLeft;
}
public get clientRectScale(): number {
if (!this._clientRectRead) {
this.readClientRect();
}
return this._clientRectScale;
}
public readonly endNode: HTMLElement;
constructor(domNode: HTMLElement, endNode: HTMLElement) {
this._domNode = domNode;
this._clientRectDeltaLeft = 0;
this._clientRectDeltaLeftRead = false;
this._clientRectScale = 1;
this._clientRectRead = false;
this.endNode = endNode;
}
@ -587,7 +605,7 @@ class RenderedViewLine implements IRenderedViewLine {
private _actualReadPixelOffset(domNode: FastDomNode<HTMLElement>, lineNumber: number, column: number, context: DomReadingContext): number {
if (this._characterMapping.length === 0) {
// This line has no content
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), 0, 0, 0, 0, context.clientRectDeltaLeft, context.endNode);
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), 0, 0, 0, 0, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);
if (!r || r.length === 0) {
return -1;
}
@ -601,7 +619,7 @@ class RenderedViewLine implements IRenderedViewLine {
const domPosition = this._characterMapping.getDomPosition(column);
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), domPosition.partIndex, domPosition.charIndex, domPosition.partIndex, domPosition.charIndex, context.clientRectDeltaLeft, context.endNode);
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), domPosition.partIndex, domPosition.charIndex, domPosition.partIndex, domPosition.charIndex, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);
if (!r || r.length === 0) {
return -1;
}
@ -627,7 +645,7 @@ class RenderedViewLine implements IRenderedViewLine {
const startDomPosition = this._characterMapping.getDomPosition(startColumn);
const endDomPosition = this._characterMapping.getDomPosition(endColumn);
return RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), startDomPosition.partIndex, startDomPosition.charIndex, endDomPosition.partIndex, endDomPosition.charIndex, context.clientRectDeltaLeft, context.endNode);
return RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), startDomPosition.partIndex, startDomPosition.charIndex, endDomPosition.partIndex, endDomPosition.charIndex, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);
}
/**

View file

@ -1593,11 +1593,12 @@ class InnerMinimap extends Disposable {
this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration.range, decorationColor, layout, line, lineHeight, lineHeight, tabSize, characterWidth, canvasInnerWidth);
continue;
case MinimapPosition.Gutter:
case MinimapPosition.Gutter: {
const y = (line - layout.startLineNumber) * lineHeight;
const x = 2;
this.renderDecoration(canvasContext, decorationColor, x, y, GUTTER_DECORATION_WIDTH, lineHeight);
continue;
}
}
}
}

View file

@ -131,7 +131,7 @@ class Parser {
case TokenKind.Text:
return token.astNode as TextAstNode;
case TokenKind.OpeningBracket:
case TokenKind.OpeningBracket: {
const set = openedBracketIds.merge(token.bracketIds);
const child = this.parseList(set);
@ -154,7 +154,7 @@ class Parser {
null
);
}
}
default:
throw new Error('unexpected');
}

View file

@ -44,7 +44,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
const charCode = text.charCodeAt(charIndex);
switch (charCode) {
case CharCode.Tab:
case CharCode.Tab: {
let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;
tabsCharDelta += insertSpacesCount - 1;
while (insertSpacesCount > 0) {
@ -58,7 +58,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
insertSpacesCount--;
}
break;
}
case CharCode.LessThan:
partContent += '&lt;';
prevIsSpace = false;

View file

@ -103,10 +103,10 @@ export class UnicodeTextModelHighlighter {
case SimpleHighlightReason.Invisible:
return { kind: UnicodeHighlighterReasonKind.Invisible };
case SimpleHighlightReason.Ambiguous:
case SimpleHighlightReason.Ambiguous: {
const primaryConfusable = strings.AmbiguousCharacters.getPrimaryConfusable(char.codePointAt(0)!)!;
return { kind: UnicodeHighlighterReasonKind.Ambiguous, confusableWith: String.fromCodePoint(primaryConfusable) };
}
case SimpleHighlightReason.NonBasicASCII:
return { kind: UnicodeHighlighterReasonKind.NonBasicAscii };
}

View file

@ -449,11 +449,11 @@ export class FindController extends CommonFindController implements IFindControl
case 'never':
updateSearchScope = false;
break;
case 'multiline':
case 'multiline': {
const isSelectionMultipleLine = !!selection && selection.startLineNumber !== selection.endLineNumber;
updateSearchScope = isSelectionMultipleLine;
break;
}
default:
break;
}

View file

@ -506,11 +506,11 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL
case 'never':
this._toggleSelectionFind.checked = false;
break;
case 'multiline':
case 'multiline': {
const isSelectionMultipleLine = !!selection && selection.startLineNumber !== selection.endLineNumber;
this._toggleSelectionFind.checked = isSelectionMultipleLine;
break;
}
default:
break;
}

View file

@ -396,7 +396,7 @@ export class FoldingController extends Disposable implements IEditorContribution
const range = e.target.range;
let iconClicked = false;
switch (e.target.type) {
case MouseTargetType.GUTTER_LINE_DECORATIONS:
case MouseTargetType.GUTTER_LINE_DECORATIONS: {
const data = e.target.detail as IMarginData;
const offsetLeftInGutter = (e.target.element as HTMLElement).offsetLeft;
const gutterOffsetX = data.offsetX - offsetLeftInGutter;
@ -410,6 +410,7 @@ export class FoldingController extends Disposable implements IEditorContribution
iconClicked = true;
break;
}
case MouseTargetType.CONTENT_EMPTY: {
if (this._unfoldOnClickAfterEndOfLine && this.hiddenRangeModel.hasRanges()) {
const data = e.target.detail as IEmptyContentData;

View file

@ -137,6 +137,10 @@
display: flex;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label {
color: var(--vscode-editorSuggestWidget-foreground);
}
.monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight {
font-weight: bold;
}

View file

@ -326,7 +326,9 @@ export function setColorMap(colorMap: string[] | null): void {
}
/**
* Set the tokens provider for a language (manual implementation).
* Set the tokens provider for a language (manual implementation). This tokenizer will be exclusive
* with a tokenizer created using `setMonarchTokensProvider`, but will work together with a tokens provider
* set using `registerDocumentSemanticTokensProvider` or `registerDocumentRangeSemanticTokensProvider`.
*/
export function setTokensProvider(languageId: string, provider: TokensProvider | EncodedTokensProvider | Thenable<TokensProvider | EncodedTokensProvider>): IDisposable {
const validLanguageId = StaticServices.languageService.get().validateLanguageId(languageId);
@ -353,7 +355,9 @@ export function setTokensProvider(languageId: string, provider: TokensProvider |
/**
* Set the tokens provider for a language (monarch implementation).
* Set the tokens provider for a language (monarch implementation). This tokenizer will be exclusive
* with a tokenizer set using `setTokensProvider`, but will work together with a tokens provider
* set using `registerDocumentSemanticTokensProvider` or `registerDocumentRangeSemanticTokensProvider`.
*/
export function setMonarchTokensProvider(languageId: string, languageDef: IMonarchLanguage | Thenable<IMonarchLanguage>): IDisposable {
const create = (languageDef: IMonarchLanguage) => {
@ -539,14 +543,22 @@ export function registerSelectionRangeProvider(languageId: string, provider: mod
}
/**
* Register a document semantic tokens provider
* Register a document semantic tokens provider. A semantic tokens provider will complement and enhance a
* simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`
* or `setTokensProvider`.
*
* For the best user experience, register both a semantic tokens provider and a top-down tokenizer.
*/
export function registerDocumentSemanticTokensProvider(languageId: string, provider: modes.DocumentSemanticTokensProvider): IDisposable {
return modes.DocumentSemanticTokensProviderRegistry.register(languageId, provider);
}
/**
* Register a document range semantic tokens provider
* Register a document range semantic tokens provider. A semantic tokens provider will complement and enhance a
* simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`
* or `setTokensProvider`.
*
* For the best user experience, register both a semantic tokens provider and a top-down tokenizer.
*/
export function registerDocumentRangeSemanticTokensProvider(languageId: string, provider: modes.DocumentRangeSemanticTokensProvider): IDisposable {
return modes.DocumentRangeSemanticTokensProviderRegistry.register(languageId, provider);

20
src/vs/monaco.d.ts vendored
View file

@ -5351,12 +5351,16 @@ declare namespace monaco.languages {
export function setColorMap(colorMap: string[] | null): void;
/**
* Set the tokens provider for a language (manual implementation).
* Set the tokens provider for a language (manual implementation). This tokenizer will be exclusive
* with a tokenizer created using `setMonarchTokensProvider`, but will work together with a tokens provider
* set using `registerDocumentSemanticTokensProvider` or `registerDocumentRangeSemanticTokensProvider`.
*/
export function setTokensProvider(languageId: string, provider: TokensProvider | EncodedTokensProvider | Thenable<TokensProvider | EncodedTokensProvider>): IDisposable;
/**
* Set the tokens provider for a language (monarch implementation).
* Set the tokens provider for a language (monarch implementation). This tokenizer will be exclusive
* with a tokenizer set using `setTokensProvider`, but will work together with a tokens provider
* set using `registerDocumentSemanticTokensProvider` or `registerDocumentRangeSemanticTokensProvider`.
*/
export function setMonarchTokensProvider(languageId: string, languageDef: IMonarchLanguage | Thenable<IMonarchLanguage>): IDisposable;
@ -5466,12 +5470,20 @@ declare namespace monaco.languages {
export function registerSelectionRangeProvider(languageId: string, provider: SelectionRangeProvider): IDisposable;
/**
* Register a document semantic tokens provider
* Register a document semantic tokens provider. A semantic tokens provider will complement and enhance a
* simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`
* or `setTokensProvider`.
*
* For the best user experience, register both a semantic tokens provider and a top-down tokenizer.
*/
export function registerDocumentSemanticTokensProvider(languageId: string, provider: DocumentSemanticTokensProvider): IDisposable;
/**
* Register a document range semantic tokens provider
* Register a document range semantic tokens provider. A semantic tokens provider will complement and enhance a
* simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`
* or `setTokensProvider`.
*
* For the best user experience, register both a semantic tokens provider and a top-down tokenizer.
*/
export function registerDocumentRangeSemanticTokensProvider(languageId: string, provider: DocumentRangeSemanticTokensProvider): IDisposable;

View file

@ -245,6 +245,8 @@ export class DialogMainService implements IDialogMainService {
// we figure this out by `hashing` the configuration
// options for the dialog to prevent duplicates
this.logService.trace('[DialogMainService]: request to acquire file dialog lock', options);
let windowFileDialogLocks = this.windowFileDialogLocks.get(window.id);
if (!windowFileDialogLocks) {
windowFileDialogLocks = new Set();
@ -256,9 +258,13 @@ export class DialogMainService implements IDialogMainService {
return undefined; // prevent duplicates, return
}
this.logService.trace('[DialogMainService]: new file dialog lock created', options);
windowFileDialogLocks.add(optionsHash);
return toDisposable(() => {
this.logService.trace('[DialogMainService]: file dialog lock disposed', options);
windowFileDialogLocks?.delete(optionsHash);
// if the window has no more dialog locks, delete it from the set of locks

View file

@ -414,6 +414,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
throw new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Can't install '{0}' extension because it is not compatible with the current version of {1} (version {2}).", extension.identifier.id, this.productService.nameLong, this.productService.version), ExtensionManagementErrorCode.Incompatible);
}
this.logService.info('Getting Manifest...', compatibleExtension.identifier.id);
const manifest = await this.galleryService.getManifest(compatibleExtension, CancellationToken.None);
if (manifest === null) {
throw new ExtensionManagementError(`Missing manifest for extension ${extension.identifier.id}`, ExtensionManagementErrorCode.Invalid);

View file

@ -175,15 +175,17 @@ export class ExtensionTipsService extends BaseExtensionTipsService {
case RecommendationsNotificationResult.Ignored:
this.highImportanceTipsByExe.delete(exeName);
break;
case RecommendationsNotificationResult.IncompatibleWindow:
case RecommendationsNotificationResult.IncompatibleWindow: {
// Recommended in incompatible window. Schedule the prompt after active window change
const onActiveWindowChange = Event.once(Event.latch(Event.any(this.nativeHostService.onDidOpenWindow, this.nativeHostService.onDidFocusWindow)));
this._register(onActiveWindowChange(() => this.promptHighImportanceExeBasedTip()));
break;
case RecommendationsNotificationResult.TooMany:
}
case RecommendationsNotificationResult.TooMany: {
// Too many notifications. Schedule the prompt after one hour
const disposable = this._register(disposableTimeout(() => { disposable.dispose(); this.promptHighImportanceExeBasedTip(); }, 60 * 60 * 1000 /* 1 hour */));
break;
}
}
});
}
@ -209,7 +211,7 @@ export class ExtensionTipsService extends BaseExtensionTipsService {
this.promptExeRecommendations(tips)
.then(result => {
switch (result) {
case RecommendationsNotificationResult.Accepted:
case RecommendationsNotificationResult.Accepted: {
// Accepted: Update the last prompted time and caches.
this.updateLastPromptedMediumExeTime(Date.now());
this.mediumImportanceTipsByExe.delete(exeName);
@ -218,23 +220,24 @@ export class ExtensionTipsService extends BaseExtensionTipsService {
// Schedule the next recommendation for next internval
const disposable1 = this._register(disposableTimeout(() => { disposable1.dispose(); this.promptMediumImportanceExeBasedTip(); }, promptInterval));
break;
}
case RecommendationsNotificationResult.Ignored:
// Ignored: Remove from the cache and prompt next recommendation
this.mediumImportanceTipsByExe.delete(exeName);
this.promptMediumImportanceExeBasedTip();
break;
case RecommendationsNotificationResult.IncompatibleWindow:
case RecommendationsNotificationResult.IncompatibleWindow: {
// Recommended in incompatible window. Schedule the prompt after active window change
const onActiveWindowChange = Event.once(Event.latch(Event.any(this.nativeHostService.onDidOpenWindow, this.nativeHostService.onDidFocusWindow)));
this._register(onActiveWindowChange(() => this.promptMediumImportanceExeBasedTip()));
break;
case RecommendationsNotificationResult.TooMany:
}
case RecommendationsNotificationResult.TooMany: {
// Too many notifications. Schedule the prompt after one hour
const disposable2 = this._register(disposableTimeout(() => { disposable2.dispose(); this.promptMediumImportanceExeBasedTip(); }, 60 * 60 * 1000 /* 1 hour */));
break;
}
}
});
}

View file

@ -23,7 +23,7 @@ export interface IRecursiveWatcher {
readonly onDidLogMessage: Event<ILogMessage>;
/**
* An event to indicate an error occured from the watcher
* An event to indicate an error occurred from the watcher
* that is unrecoverable. Listeners should restart the
* watcher if possible.
*/

View file

@ -397,13 +397,10 @@ export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider imple
} catch (error) {
throw this.toFileSystemProviderError(error);
} finally {
// Release any known lock for the file handle
// since the handle has been closed and is invalid
const lockForHandle = this.mapHandleToLock.get(fd);
if (lockForHandle) {
lockForHandle.dispose();
this.mapHandleToLock.delete(fd);
lockForHandle.dispose();
}
}
}

View file

@ -323,7 +323,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
await Promises.unlink(source);
} catch (error) {
switch (error.code) {
case 'EACCES':
case 'EACCES': {
const { response } = await this.showMessageBox(windowId, {
title: this.productService.nameLong,
type: 'info',
@ -346,6 +346,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
}
}
break;
}
case 'ENOENT':
break; // ignore file not found
default:

View file

@ -298,7 +298,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
case TriggerAction.REFRESH_PICKER:
updatePickerItems();
break;
case TriggerAction.REMOVE_ITEM:
case TriggerAction.REMOVE_ITEM: {
const index = picker.items.indexOf(item);
if (index !== -1) {
const items = picker.items.slice();
@ -313,6 +313,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
picker.keepScrollPosition = keepScrollPositionBefore;
}
break;
}
}
}
}

View file

@ -473,11 +473,13 @@ export class PersistentTerminalProcess extends Disposable {
get fixedDimensions(): IFixedTerminalDimensions | undefined { return this._fixedDimensions; }
setTitle(title: string, titleSource: TitleEventSource): void {
this._hasWrittenData = true;
this._title = title;
this._titleSource = titleSource;
}
setIcon(icon: TerminalIcon, color?: string): void {
this._hasWrittenData = true;
this._icon = icon;
this._color = color;
}

View file

@ -399,20 +399,22 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
async refreshProperty<T extends ProcessPropertyType>(type: T): Promise<IProcessPropertyMap[T]> {
switch (type) {
case ProcessPropertyType.Cwd:
case ProcessPropertyType.Cwd: {
const newCwd = await this.getCwd();
if (newCwd !== this._properties.cwd) {
this._properties.cwd = newCwd;
this._onDidChangeProperty.fire({ type: ProcessPropertyType.Cwd, value: this._properties.cwd });
}
return newCwd as IProcessPropertyMap[T];
case ProcessPropertyType.InitialCwd:
}
case ProcessPropertyType.InitialCwd: {
const initialCwd = await this.getInitialCwd();
if (initialCwd !== this._properties.initialCwd) {
this._properties.initialCwd = initialCwd;
this._onDidChangeProperty.fire({ type: ProcessPropertyType.InitialCwd, value: this._properties.initialCwd });
}
return initialCwd as IProcessPropertyMap[T];
}
case ProcessPropertyType.Title:
return this.currentTitle as IProcessPropertyMap[T];
default:

View file

@ -555,7 +555,7 @@ export function executeTransform(transform: ColorTransform, theme: IColorTheme)
case ColorTransformType.IfDefinedThenElse:
return resolveColorValue(theme.defines(transform.if) ? transform.then : transform.else, theme);
case ColorTransformType.LessProminent:
case ColorTransformType.LessProminent: {
const from = resolveColorValue(transform.value, theme);
if (!from) {
return undefined;
@ -569,6 +569,7 @@ export function executeTransform(transform: ColorTransform, theme: IColorTheme)
return from.isDarkerThan(backgroundColor)
? Color.getLighterColor(from, backgroundColor, transform.factor).transparent(transform.transparency)
: Color.getDarkerColor(from, backgroundColor, transform.factor).transparent(transform.transparency);
}
default:
throw assertNever(transform);
}

View file

@ -839,7 +839,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
case 'one':
case 'all':
case 'preserve':
case 'folders':
case 'folders': {
// Collect previously opened windows
const lastSessionWindows: IWindowState[] = [];
@ -876,6 +876,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
return pathsToOpen;
}
}
}

View file

@ -7,7 +7,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { ExtHostContext, IExtHostEditorTabsShape, IExtHostContext, MainContext, IEditorTabDto } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { EditorResourceAccessor, IUntypedEditorInput, SideBySideEditor, GroupChangeKind } from 'vs/workbench/common/editor';
import { EditorResourceAccessor, IUntypedEditorInput, SideBySideEditor, GroupModelChangeKind } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { isGroupEditorCloseEvent, isGroupEditorMoveEvent, isGroupEditorOpenEvent } from 'vs/workbench/common/editor/editorGroupModel';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
@ -157,7 +157,7 @@ export class MainThreadEditorTabs {
}
private _onDidGroupActivate(event: IEditorsChangeEvent): void {
if (event.kind !== GroupChangeKind.GROUP_INDEX && event.kind !== GroupChangeKind.EDITOR_ACTIVE) {
if (event.kind !== GroupModelChangeKind.GROUP_INDEX && event.kind !== GroupModelChangeKind.EDITOR_ACTIVE) {
return;
}
this._findAndUpdateActiveTab();
@ -188,15 +188,15 @@ export class MainThreadEditorTabs {
// let eventString = '[';
// events.forEach(event => {
// switch (event.kind) {
// case GroupChangeKind.GROUP_INDEX: eventString += 'GROUP_INDEX, '; break;
// case GroupChangeKind.EDITOR_ACTIVE: eventString += 'EDITOR_ACTIVE, '; break;
// case GroupChangeKind.EDITOR_PIN: eventString += 'EDITOR_PIN, '; break;
// case GroupChangeKind.EDITOR_OPEN: eventString += 'EDITOR_OPEN, '; break;
// case GroupChangeKind.EDITOR_CLOSE: eventString += 'EDITOR_CLOSE, '; break;
// case GroupChangeKind.EDITOR_MOVE: eventString += 'EDITOR_MOVE, '; break;
// case GroupChangeKind.EDITOR_LABEL: eventString += 'EDITOR_LABEL, '; break;
// case GroupChangeKind.GROUP_ACTIVE: eventString += 'GROUP_ACTIVE, '; break;
// case GroupChangeKind.GROUP_LOCKED: eventString += 'GROUP_LOCKED, '; break;
// case GroupModelChangeKind.GROUP_INDEX: eventString += 'GROUP_INDEX, '; break;
// case GroupModelChangeKind.EDITOR_ACTIVE: eventString += 'EDITOR_ACTIVE, '; break;
// case GroupModelChangeKind.EDITOR_PIN: eventString += 'EDITOR_PIN, '; break;
// case GroupModelChangeKind.EDITOR_OPEN: eventString += 'EDITOR_OPEN, '; break;
// case GroupModelChangeKind.EDITOR_CLOSE: eventString += 'EDITOR_CLOSE, '; break;
// case GroupModelChangeKind.EDITOR_MOVE: eventString += 'EDITOR_MOVE, '; break;
// case GroupModelChangeKind.EDITOR_LABEL: eventString += 'EDITOR_LABEL, '; break;
// case GroupModelChangeKind.GROUP_ACTIVE: eventString += 'GROUP_ACTIVE, '; break;
// case GroupModelChangeKind.GROUP_LOCKED: eventString += 'GROUP_LOCKED, '; break;
// default: eventString += 'UNKNOWN, '; break;
// }
// });
@ -212,24 +212,24 @@ export class MainThreadEditorTabs {
events.forEach(event => {
// Call the correct function for the change type
switch (event.kind) {
case GroupChangeKind.EDITOR_OPEN:
case GroupModelChangeKind.EDITOR_OPEN:
this._onDidTabOpen(event);
break;
case GroupChangeKind.EDITOR_CLOSE:
case GroupModelChangeKind.EDITOR_CLOSE:
this._onDidTabClose(event);
break;
case GroupChangeKind.EDITOR_ACTIVE:
case GroupChangeKind.GROUP_ACTIVE:
case GroupModelChangeKind.EDITOR_ACTIVE:
case GroupModelChangeKind.GROUP_ACTIVE:
if (this._editorGroupsService.activeGroup.id !== event.groupId) {
return;
}
this._onDidGroupActivate(event);
break;
case GroupChangeKind.GROUP_INDEX:
case GroupModelChangeKind.GROUP_INDEX:
this._createTabsModel();
// Here we stop the loop as no need to process other events
break;
case GroupChangeKind.EDITOR_MOVE:
case GroupModelChangeKind.EDITOR_MOVE:
this._onDidTabMove(event);
break;
default:

View file

@ -247,9 +247,10 @@ class SaveWorkspaceAsAction extends Action2 {
if (configPathUri && hasWorkspaceFileExtension(configPathUri)) {
switch (contextService.getWorkbenchState()) {
case WorkbenchState.EMPTY:
case WorkbenchState.FOLDER:
case WorkbenchState.FOLDER: {
const folders = contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri }));
return workspaceEditingService.createAndEnterWorkspace(folders, configPathUri);
}
case WorkbenchState.WORKSPACE:
return workspaceEditingService.saveAndEnterWorkspace(configPathUri);
}

View file

@ -963,29 +963,32 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
case Parts.EDITOR_PART:
this.editorGroupService.activeGroup.focus();
break;
case Parts.PANEL_PART:
case Parts.PANEL_PART: {
const activePanel = this.paneCompositeService.getActivePaneComposite(ViewContainerLocation.Panel);
if (activePanel) {
activePanel.focus();
}
break;
case Parts.SIDEBAR_PART:
}
case Parts.SIDEBAR_PART: {
const activeViewlet = this.paneCompositeService.getActivePaneComposite(ViewContainerLocation.Sidebar);
if (activeViewlet) {
activeViewlet.focus();
}
break;
}
case Parts.ACTIVITYBAR_PART:
(this.getPart(Parts.ACTIVITYBAR_PART) as ActivitybarPart).focus();
break;
case Parts.STATUSBAR_PART:
this.statusBarService.focus();
default:
default: {
// Title Bar & Banner simply pass focus to container
const container = this.getContainer(part);
if (container) {
container.focus();
}
}
}
}

View file

@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/editorgroupview';
import { EditorGroupModel, IEditorOpenOptions, IGroupChangeEvent, IGroupEditorCloseEvent, IGroupEditorMoveEvent, IGroupEditorOpenEvent, ISerializedEditorGroupModel, isGroupEditorCloseEvent, isGroupEditorMoveEvent, isGroupEditorOpenEvent, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel';
import { GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, EditorInputCapabilities, IUntypedEditorInput, DEFAULT_EDITOR_ASSOCIATION, ActiveEditorGroupLockedContext, SideBySideEditor, EditorCloseContext, IEditorWillMoveEvent, IEditorWillOpenEvent, IMatchEditorOptions, GroupChangeKind } from 'vs/workbench/common/editor';
import { EditorGroupModel, IEditorOpenOptions, IGroupModelChangeEvent, ISerializedEditorGroupModel, isGroupEditorCloseEvent, isGroupEditorOpenEvent, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel';
import { GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, EditorInputCapabilities, IUntypedEditorInput, DEFAULT_EDITOR_ASSOCIATION, ActiveEditorGroupLockedContext, SideBySideEditor, EditorCloseContext, IEditorWillMoveEvent, IEditorWillOpenEvent, IMatchEditorOptions, GroupModelChangeKind, IActiveEditorChangeEvent } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { Event, Emitter, Relay } from 'vs/base/common/event';
@ -87,12 +87,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private readonly _onWillDispose = this._register(new Emitter<void>());
readonly onWillDispose = this._onWillDispose.event;
private readonly _onDidGroupChange = this._register(new Emitter<IGroupChangeEvent>());
readonly onDidGroupChange = this._onDidGroupChange.event;
private readonly _onDidModelChange = this._register(new Emitter<IGroupChangeEvent>());
private readonly _onDidModelChange = this._register(new Emitter<IGroupModelChangeEvent>());
readonly onDidModelChange = this._onDidModelChange.event;
private readonly _onDidActiveEditorChange = this._register(new Emitter<IActiveEditorChangeEvent>());
readonly onDidActiveEditorChange = this._onDidActiveEditorChange.event;
private readonly _onDidOpenEditorFail = this._register(new Emitter<EditorInput>());
readonly onDidOpenEditorFail = this._onDidOpenEditorFail.event;
@ -266,32 +266,33 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
};
// Update group contexts based on group changes
this._register(this.onDidGroupChange(e => {
this._register(this.onDidModelChange(e => {
switch (e.kind) {
case GroupChangeKind.EDITOR_ACTIVE:
// Track the active editor and update context key that reflects
// the dirty state of this editor
observeActiveEditor();
case GroupModelChangeKind.GROUP_LOCKED:
groupLockedContext.set(this.isLocked);
break;
case GroupChangeKind.EDITOR_PIN:
case GroupModelChangeKind.EDITOR_PIN:
if (e.editor && e.editor === this.model.activeEditor) {
groupActiveEditorPinnedContext.set(this.model.isPinned(this.model.activeEditor));
}
break;
case GroupChangeKind.EDITOR_STICKY:
case GroupModelChangeKind.EDITOR_STICKY:
if (e.editor && e.editor === this.model.activeEditor) {
groupActiveEditorStickyContext.set(this.model.isSticky(this.model.activeEditor));
}
break;
case GroupChangeKind.GROUP_LOCKED:
groupLockedContext.set(this.isLocked);
break;
}
// Group editors count context
groupEditorsCountContext.set(this.count);
}));
// Track the active editor and update context key that reflects
// the dirty state of this editor
this._register(this.onDidActiveEditorChange(() => {
observeActiveEditor();
}));
observeActiveEditor();
}
@ -535,76 +536,40 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this._register(this.accessor.onDidVisibilityChange(e => this.onDidVisibilityChange(e)));
}
private onDidGroupModelChange(e: IGroupChangeEvent): void {
private onDidGroupModelChange(e: IGroupModelChangeEvent): void {
// Re-emit to outside
this._onDidModelChange.fire(e);
// Handle within
if (e.kind === GroupChangeKind.GROUP_LOCKED) {
this.onDidChangeGroupLocked();
return;
}
if (!e.editor) {
return;
}
switch (e.kind) {
case GroupChangeKind.EDITOR_PIN:
this.onDidChangeEditorPinned(e.editor);
break;
case GroupChangeKind.EDITOR_STICKY:
this.onDidChangeEditorSticky(e.editor);
break;
case GroupChangeKind.EDITOR_MOVE:
if (isGroupEditorMoveEvent(e)) {
this.onDidMoveEditor(e.editor, e.oldEditorIndex, e.editorIndex);
}
break;
case GroupChangeKind.EDITOR_OPEN:
case GroupModelChangeKind.EDITOR_OPEN:
if (isGroupEditorOpenEvent(e)) {
this.onDidOpenEditor(e.editor, e.editorIndex);
}
break;
case GroupChangeKind.EDITOR_CLOSE:
case GroupModelChangeKind.EDITOR_CLOSE:
if (isGroupEditorCloseEvent(e)) {
this.handleOnDidCloseEditor(e.editor, e.editorIndex, e.context, e.sticky);
}
break;
case GroupChangeKind.EDITOR_WILL_DISPOSE:
case GroupModelChangeKind.EDITOR_WILL_DISPOSE:
this.onWillDisposeEditor(e.editor);
break;
case GroupChangeKind.EDITOR_DIRTY:
case GroupModelChangeKind.EDITOR_DIRTY:
this.onDidChangeEditorDirty(e.editor);
break;
case GroupChangeKind.EDITOR_LABEL:
case GroupModelChangeKind.EDITOR_LABEL:
this.onDidChangeEditorLabel(e.editor);
break;
case GroupChangeKind.EDITOR_CAPABILITIES:
this.onDidChangeEditorCapabilities(e.editor);
break;
}
}
private onDidChangeGroupLocked(): void {
this._onDidGroupChange.fire({ kind: GroupChangeKind.GROUP_LOCKED });
}
private onDidChangeEditorPinned(editor: EditorInput): void {
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_PIN, editor });
}
private onDidChangeEditorSticky(editor: EditorInput): void {
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_STICKY, editor });
}
private onDidMoveEditor(editor: EditorInput, oldEditorIndex: number, editorIndex: number): void {
const event: IGroupEditorMoveEvent = { kind: GroupChangeKind.EDITOR_MOVE, editor, oldEditorIndex, editorIndex };
this._onDidGroupChange.fire(event);
}
private onDidOpenEditor(editor: EditorInput, editorIndex: number): void {
/* __GDPR__
@ -618,10 +583,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Update container
this.updateContainer();
// Event
const event: IGroupEditorOpenEvent = { kind: GroupChangeKind.EDITOR_OPEN, editor, editorIndex };
this._onDidGroupChange.fire(event);
}
private handleOnDidCloseEditor(editor: EditorInput, editorIndex: number, context: EditorCloseContext, sticky: boolean): void {
@ -661,8 +622,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Event
this._onDidCloseEditor.fire({ groupId: this.id, editor, context, index: editorIndex, sticky });
const event: IGroupEditorCloseEvent = { kind: GroupChangeKind.EDITOR_CLOSE, editor, editorIndex, context, sticky };
this._onDidGroupChange.fire(event);
}
private canDispose(editor: EditorInput): boolean {
@ -776,24 +735,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Forward to title control
this.titleAreaControl.updateEditorDirty(editor);
// Event
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_DIRTY, editor });
}
private onDidChangeEditorLabel(editor: EditorInput): void {
// Forward to title control
this.titleAreaControl.updateEditorLabel(editor);
// Event
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_LABEL, editor });
}
private onDidChangeEditorCapabilities(editor: EditorInput): void {
// Event
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_CAPABILITIES, editor });
}
private onDidVisibilityChange(visible: boolean): void {
@ -843,8 +790,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
if (this._index !== newIndex) {
this._index = newIndex;
this.model.setIndex(newIndex);
this._onDidGroupChange.fire({ kind: GroupChangeKind.GROUP_INDEX });
}
}
@ -861,8 +806,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Update styles
this.updateStyles();
// Event
this._onDidGroupChange.fire({ kind: GroupChangeKind.GROUP_ACTIVE });
// Update model
this.model.setActive(undefined /* entire group got active */);
}
//#endregion
@ -1119,7 +1064,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Editor change event
if (changed) {
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_ACTIVE, editor });
this._onDidActiveEditorChange.fire({ editor });
}
// Handle errors but do not bubble them up
@ -1535,7 +1480,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
// Events
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_ACTIVE });
this._onDidActiveEditorChange.fire({ editor: undefined });
// Remove empty group if we should
if (closeEmptyGroup) {
@ -1690,7 +1635,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Otherwise, handle accordingly
switch (confirmation) {
case ConfirmResult.SAVE:
case ConfirmResult.SAVE: {
const result = await editor.save(this.id, { reason: saveReason });
if (!result && autoSave) {
// Save failed and we need to signal this back to the user, so
@ -1701,6 +1646,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
return editor.isDirty(); // veto if still dirty
}
case ConfirmResult.DONT_SAVE:
try {

View file

@ -11,7 +11,7 @@ import { contrastBorder, editorBackground } from 'vs/platform/theme/common/color
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, GroupsOrder, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument, IEditorGroupsService, IEditorSideGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IView, orthogonal, LayoutPriority, IViewSize, Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid } from 'vs/base/browser/ui/grid/grid';
import { GroupIdentifier, EditorInputWithOptions, IEditorPartOptions, IEditorPartOptionsChangeEvent, GroupChangeKind } from 'vs/workbench/common/editor';
import { GroupIdentifier, EditorInputWithOptions, IEditorPartOptions, IEditorPartOptionsChangeEvent, GroupModelChangeKind } from 'vs/workbench/common/editor';
import { EDITOR_GROUP_BORDER, EDITOR_PANE_BACKGROUND } from 'vs/workbench/common/theme';
import { distinct, coalesce, firstOrDefault } from 'vs/base/common/arrays';
import { IEditorGroupsAccessor, IEditorGroupView, getEditorPartOptions, impactsEditorPartOptions, IEditorPartCreationOptions } from 'vs/workbench/browser/parts/editor/editor';
@ -237,20 +237,21 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
case GroupsOrder.CREATION_TIME:
return this.groups;
case GroupsOrder.MOST_RECENTLY_ACTIVE:
case GroupsOrder.MOST_RECENTLY_ACTIVE: {
const mostRecentActive = coalesce(this.mostRecentActiveGroups.map(groupId => this.getGroup(groupId)));
// there can be groups that got never active, even though they exist. in this case
// make sure to just append them at the end so that all groups are returned properly
return distinct([...mostRecentActive, ...this.groups]);
case GroupsOrder.GRID_APPEARANCE:
}
case GroupsOrder.GRID_APPEARANCE: {
const views: IEditorGroupView[] = [];
if (this.gridWidget) {
this.fillGridNodes(views, this.gridWidget.getViews());
}
return views;
}
}
}
@ -301,20 +302,22 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
return groups[0];
case GroupLocation.LAST:
return groups[groups.length - 1];
case GroupLocation.NEXT:
case GroupLocation.NEXT: {
let nextGroup: IEditorGroupView | undefined = groups[index + 1];
if (!nextGroup && wrap) {
nextGroup = this.doFindGroupByLocation(GroupLocation.FIRST, source);
}
return nextGroup;
case GroupLocation.PREVIOUS:
}
case GroupLocation.PREVIOUS: {
let previousGroup: IEditorGroupView | undefined = groups[index - 1];
if (!previousGroup && wrap) {
previousGroup = this.doFindGroupByLocation(GroupLocation.LAST, source);
}
return previousGroup;
}
}
}
@ -550,21 +553,23 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
this.doSetGroupActive(groupView);
}));
// Track editor change
groupDisposables.add(groupView.onDidGroupChange(e => {
// Track group changes
groupDisposables.add(groupView.onDidModelChange(e => {
switch (e.kind) {
case GroupChangeKind.EDITOR_ACTIVE:
this.updateContainer();
break;
case GroupChangeKind.GROUP_INDEX:
this._onDidChangeGroupIndex.fire(groupView);
break;
case GroupChangeKind.GROUP_LOCKED:
case GroupModelChangeKind.GROUP_LOCKED:
this._onDidChangeGroupLocked.fire(groupView);
break;
case GroupModelChangeKind.GROUP_INDEX:
this._onDidChangeGroupIndex.fire(groupView);
break;
}
}));
// Track active editor change after it occurred
groupDisposables.add(groupView.onDidActiveEditorChange(() => {
this.updateContainer();
}));
// Track dispose
Event.once(groupView.onWillDispose)(() => {
dispose(groupDisposables);

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IEditorFactoryRegistry, IEditorIdentifier, GroupIdentifier, EditorExtensions, IEditorPartOptionsChangeEvent, EditorsOrder, GroupChangeKind } from 'vs/workbench/common/editor';
import { IEditorFactoryRegistry, IEditorIdentifier, GroupIdentifier, EditorExtensions, IEditorPartOptionsChangeEvent, EditorsOrder, GroupModelChangeKind } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
@ -115,11 +115,11 @@ export class EditorsObserver extends Disposable {
private registerGroupListeners(group: IEditorGroup): void {
const groupDisposables = new DisposableStore();
groupDisposables.add(group.onDidGroupChange(e => {
groupDisposables.add(group.onDidModelChange(e => {
switch (e.kind) {
// Group gets active: put active editor as most recent
case GroupChangeKind.GROUP_ACTIVE: {
case GroupModelChangeKind.GROUP_ACTIVE: {
if (this.editorGroupsService.activeGroup === group && group.activeEditor) {
this.addMostRecentEditor(group, group.activeEditor, true /* is active */, false /* editor already opened */);
}
@ -127,21 +127,11 @@ export class EditorsObserver extends Disposable {
break;
}
// Editor gets active: put active editor as most recent
// if group is active, otherwise second most recent
case GroupChangeKind.EDITOR_ACTIVE: {
if (e.editor) {
this.addMostRecentEditor(group, e.editor, this.editorGroupsService.activeGroup === group, false /* editor already opened */);
}
break;
}
// Editor opens: put it as second most recent
//
// Also check for maximum allowed number of editors and
// start to close oldest ones if needed.
case GroupChangeKind.EDITOR_OPEN: {
case GroupModelChangeKind.EDITOR_OPEN: {
if (e.editor) {
this.addMostRecentEditor(group, e.editor, false /* is not active */, true /* is new */);
this.ensureOpenedEditorsLimit({ groupId: group.id, editor: e.editor }, group.id);
@ -149,15 +139,19 @@ export class EditorsObserver extends Disposable {
break;
}
}
}));
// Editor closes: remove from recently opened
case GroupChangeKind.EDITOR_CLOSE: {
if (e.editor) {
this.removeMostRecentEditor(group, e.editor);
}
// Editor closes: remove from recently opened
groupDisposables.add(group.onDidCloseEditor(e => {
this.removeMostRecentEditor(group, e.editor);
}));
break;
}
// Editor gets active: put active editor as most recent
// if group is active, otherwise second most recent
groupDisposables.add(group.onDidActiveEditorChange(e => {
if (e.editor) {
this.addMostRecentEditor(group, e.editor, this.editorGroupsService.activeGroup === group, false /* editor already opened */);
}
}));

View file

@ -13,7 +13,7 @@ import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntry
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IAction, Separator, toAction } from 'vs/base/common/actions';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme';
import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_ITEM_COMPACT_HOVER_BACKGROUND } from 'vs/workbench/common/theme';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { EventHelper, createStyleSheet, addDisposableListener, EventType, clearNode } from 'vs/base/browser/dom';
@ -414,8 +414,9 @@ export class StatusbarPart extends Part implements IStatusbarService {
// Install mouse listeners to update hover feedback for
// all compact entries that belong to each other
const statusBarItemHoverBackground = this.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND)?.toString();
const statusBarItemCompactHoverBackground = this.getColor(STATUS_BAR_ITEM_COMPACT_HOVER_BACKGROUND)?.toString();
this.compactEntriesDisposable.value = new DisposableStore();
if (statusBarItemHoverBackground && this.theme.type !== ColorScheme.HIGH_CONTRAST) {
if (statusBarItemHoverBackground && statusBarItemCompactHoverBackground && this.theme.type !== ColorScheme.HIGH_CONTRAST) {
for (const [, compactEntryGroup] of compactEntryGroups) {
for (const compactEntry of compactEntryGroup) {
if (!compactEntry.hasCommand) {
@ -424,6 +425,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
this.compactEntriesDisposable.value.add(addDisposableListener(compactEntry.labelContainer, EventType.MOUSE_OVER, () => {
compactEntryGroup.forEach(compactEntry => compactEntry.labelContainer.style.backgroundColor = statusBarItemHoverBackground);
compactEntry.labelContainer.style.backgroundColor = statusBarItemCompactHoverBackground;
}));
this.compactEntriesDisposable.value.add(addDisposableListener(compactEntry.labelContainer, EventType.MOUSE_OUT, () => {

View file

@ -226,7 +226,7 @@ class ViewPaneDropOverlay extends Themable {
case DropDirection.RIGHT:
this.doPositionOverlay({ top: '0', right: '0', width: '50%', height: '100%' });
break;
default:
default: {
// const top = this.bounds?.top || 0;
// const left = this.bounds?.bottom || 0;
@ -243,6 +243,7 @@ class ViewPaneDropOverlay extends Themable {
}
this.doPositionOverlay({ top, left, width, height });
}
}
if ((this.orientation === Orientation.VERTICAL && paneHeight <= 25) ||

View file

@ -785,6 +785,14 @@ export interface IEditorCloseEvent extends IEditorIdentifier {
readonly sticky: boolean;
}
export interface IActiveEditorChangeEvent {
/**
* The new active editor or `undefined` if the group is empty.
*/
editor: EditorInput | undefined;
}
export interface IEditorWillMoveEvent extends IEditorIdentifier {
/**
@ -823,7 +831,7 @@ export interface IEditorOpenEvent extends IEditorIdentifier {
export type GroupIdentifier = number;
export const enum GroupChangeKind {
export const enum GroupModelChangeKind {
/* Group Changes */
GROUP_ACTIVE,

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { IEditorFactoryRegistry, GroupIdentifier, EditorsOrder, EditorExtensions, IUntypedEditorInput, SideBySideEditor, EditorCloseContext, IMatchEditorOptions, GroupChangeKind } from 'vs/workbench/common/editor';
import { IEditorFactoryRegistry, GroupIdentifier, EditorsOrder, EditorExtensions, IUntypedEditorInput, SideBySideEditor, EditorCloseContext, IMatchEditorOptions, GroupModelChangeKind } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -70,12 +70,12 @@ export interface IMatchOptions {
readonly strictEquals?: boolean;
}
export interface IGroupChangeEvent {
export interface IGroupModelChangeEvent {
/**
* The kind of change that occured in the group.
* The kind of change that occured in the group model.
*/
readonly kind: GroupChangeKind;
readonly kind: GroupModelChangeKind;
/**
* Only applies when editors change providing
@ -84,13 +84,13 @@ export interface IGroupChangeEvent {
readonly editor?: EditorInput;
}
export interface IGroupEditorChangeEvent extends IGroupChangeEvent {
export interface IGroupEditorChangeEvent extends IGroupModelChangeEvent {
readonly editor: EditorInput;
}
export interface IGroupEditorOpenEvent extends IGroupEditorChangeEvent {
readonly kind: GroupChangeKind.EDITOR_OPEN;
readonly kind: GroupModelChangeKind.EDITOR_OPEN;
/**
* Identifies the index of the editor in the group.
@ -98,15 +98,15 @@ export interface IGroupEditorOpenEvent extends IGroupEditorChangeEvent {
readonly editorIndex: number;
}
export function isGroupEditorOpenEvent(e: IGroupChangeEvent): e is IGroupEditorOpenEvent {
export function isGroupEditorOpenEvent(e: IGroupModelChangeEvent): e is IGroupEditorOpenEvent {
const candidate = e as IGroupEditorOpenEvent;
return candidate.kind === GroupChangeKind.EDITOR_OPEN && candidate.editorIndex !== undefined;
return candidate.kind === GroupModelChangeKind.EDITOR_OPEN && candidate.editorIndex !== undefined;
}
export interface IGroupEditorMoveEvent extends IGroupEditorChangeEvent {
readonly kind: GroupChangeKind.EDITOR_MOVE;
readonly kind: GroupModelChangeKind.EDITOR_MOVE;
/**
* Identifies the index of the editor in the group.
@ -121,15 +121,15 @@ export interface IGroupEditorMoveEvent extends IGroupEditorChangeEvent {
readonly oldEditorIndex: number;
}
export function isGroupEditorMoveEvent(e: IGroupChangeEvent): e is IGroupEditorMoveEvent {
export function isGroupEditorMoveEvent(e: IGroupModelChangeEvent): e is IGroupEditorMoveEvent {
const candidate = e as IGroupEditorMoveEvent;
return candidate.kind === GroupChangeKind.EDITOR_MOVE && candidate.editorIndex !== undefined && candidate.oldEditorIndex !== undefined;
return candidate.kind === GroupModelChangeKind.EDITOR_MOVE && candidate.editorIndex !== undefined && candidate.oldEditorIndex !== undefined;
}
export interface IGroupEditorCloseEvent extends IGroupEditorChangeEvent {
readonly kind: GroupChangeKind.EDITOR_CLOSE;
readonly kind: GroupModelChangeKind.EDITOR_CLOSE;
/**
* Identifies the index of the editor in the group.
@ -151,10 +151,10 @@ export interface IGroupEditorCloseEvent extends IGroupEditorChangeEvent {
readonly sticky: boolean;
}
export function isGroupEditorCloseEvent(e: IGroupChangeEvent): e is IGroupEditorCloseEvent {
export function isGroupEditorCloseEvent(e: IGroupModelChangeEvent): e is IGroupEditorCloseEvent {
const candidate = e as IGroupEditorCloseEvent;
return candidate.kind === GroupChangeKind.EDITOR_CLOSE && candidate.editorIndex !== undefined && candidate.context !== undefined && candidate.sticky !== undefined;
return candidate.kind === GroupModelChangeKind.EDITOR_CLOSE && candidate.editorIndex !== undefined && candidate.context !== undefined && candidate.sticky !== undefined;
}
interface IEditorCloseResult {
@ -170,7 +170,7 @@ export class EditorGroupModel extends Disposable {
//#region events
private readonly _onDidModelChange = this._register(new Emitter<IGroupChangeEvent>());
private readonly _onDidModelChange = this._register(new Emitter<IGroupModelChangeEvent>());
readonly onDidModelChange = this._onDidModelChange.event;
//#endregion
@ -351,7 +351,7 @@ export class EditorGroupModel extends Disposable {
// Event
const event: IGroupEditorOpenEvent = {
kind: GroupChangeKind.EDITOR_OPEN,
kind: GroupModelChangeKind.EDITOR_OPEN,
editor: newEditor,
editorIndex: targetIndex
};
@ -407,7 +407,7 @@ export class EditorGroupModel extends Disposable {
listeners.add(Event.once(editor.onWillDispose)(() => {
if (this.indexOf(editor) >= 0) {
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_WILL_DISPOSE,
kind: GroupModelChangeKind.EDITOR_WILL_DISPOSE,
editor
});
}
@ -416,7 +416,7 @@ export class EditorGroupModel extends Disposable {
// Re-Emit dirty state changes
listeners.add(editor.onDidChangeDirty(() => {
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_DIRTY,
kind: GroupModelChangeKind.EDITOR_DIRTY,
editor
});
}));
@ -424,7 +424,7 @@ export class EditorGroupModel extends Disposable {
// Re-Emit label changes
listeners.add(editor.onDidChangeLabel(() => {
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_LABEL,
kind: GroupModelChangeKind.EDITOR_LABEL,
editor
});
}));
@ -432,14 +432,14 @@ export class EditorGroupModel extends Disposable {
// Re-Emit capability changes
listeners.add(editor.onDidChangeCapabilities(() => {
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_CAPABILITIES,
kind: GroupModelChangeKind.EDITOR_CAPABILITIES,
editor
});
}));
// Clean up dispose listeners once the editor gets closed
listeners.add(this.onDidModelChange(event => {
if (event.kind === GroupChangeKind.EDITOR_CLOSE && event.editor?.matches(editor)) {
if (event.kind === GroupModelChangeKind.EDITOR_CLOSE && event.editor?.matches(editor)) {
dispose(listeners);
}
}));
@ -455,7 +455,7 @@ export class EditorGroupModel extends Disposable {
if (closeResult) {
const event: IGroupEditorCloseEvent = {
kind: GroupChangeKind.EDITOR_CLOSE,
kind: GroupModelChangeKind.EDITOR_CLOSE,
...closeResult
};
this._onDidModelChange.fire(event);
@ -467,7 +467,7 @@ export class EditorGroupModel extends Disposable {
if (closeResult) {
const event: IGroupEditorCloseEvent = {
kind: GroupChangeKind.EDITOR_CLOSE,
kind: GroupModelChangeKind.EDITOR_CLOSE,
...closeResult
};
this._onDidModelChange.fire(event);
@ -556,7 +556,7 @@ export class EditorGroupModel extends Disposable {
// Event
const event: IGroupEditorMoveEvent = {
kind: GroupChangeKind.EDITOR_MOVE,
kind: GroupModelChangeKind.EDITOR_MOVE,
editor,
oldEditorIndex: index,
editorIndex: toIndex,
@ -566,7 +566,27 @@ export class EditorGroupModel extends Disposable {
return editor;
}
setActive(candidate: EditorInput): EditorInput | undefined {
setActive(candidate: EditorInput | undefined): EditorInput | undefined {
let result: EditorInput | undefined = undefined;
if (!candidate) {
this.setGroupActive();
} else {
result = this.setEditorActive(candidate);
}
return result;
}
private setGroupActive(): void {
// We do not really keep the `active` state in our model because
// it has no special meaning to us here. But for consistency
// we emit a `onDidModelChange` event so that components can
// react.
this._onDidModelChange.fire({ kind: GroupModelChangeKind.GROUP_ACTIVE });
}
private setEditorActive(candidate: EditorInput): EditorInput | undefined {
const res = this.findEditor(candidate);
if (!res) {
return; // not found
@ -593,7 +613,7 @@ export class EditorGroupModel extends Disposable {
// Event
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_ACTIVE,
kind: GroupModelChangeKind.EDITOR_ACTIVE,
editor
});
}
@ -603,7 +623,7 @@ export class EditorGroupModel extends Disposable {
// it has no special meaning to us here. But for consistency
// we emit a `onDidModelChange` event so that components can
// react.
this._onDidModelChange.fire({ kind: GroupChangeKind.GROUP_INDEX });
this._onDidModelChange.fire({ kind: GroupModelChangeKind.GROUP_INDEX });
}
pin(candidate: EditorInput): EditorInput | undefined {
@ -629,7 +649,7 @@ export class EditorGroupModel extends Disposable {
// Event
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_PIN,
kind: GroupModelChangeKind.EDITOR_PIN,
editor
});
}
@ -658,7 +678,7 @@ export class EditorGroupModel extends Disposable {
// Event
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_PIN,
kind: GroupModelChangeKind.EDITOR_PIN,
editor
});
@ -708,7 +728,7 @@ export class EditorGroupModel extends Disposable {
// Event
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_STICKY,
kind: GroupModelChangeKind.EDITOR_STICKY,
editor
});
}
@ -739,7 +759,7 @@ export class EditorGroupModel extends Disposable {
// Event
this._onDidModelChange.fire({
kind: GroupChangeKind.EDITOR_STICKY,
kind: GroupModelChangeKind.EDITOR_STICKY,
editor
});
}
@ -892,7 +912,7 @@ export class EditorGroupModel extends Disposable {
if (this.isLocked !== locked) {
this.locked = locked;
this._onDidModelChange.fire({ kind: GroupChangeKind.GROUP_LOCKED });
this._onDidModelChange.fire({ kind: GroupModelChangeKind.GROUP_LOCKED });
}
}

View file

@ -400,6 +400,12 @@ export const STATUS_BAR_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.hov
hc: Color.white.transparent(0.12)
}, localize('statusBarItemHoverBackground', "Status bar item background color when hovering. The status bar is shown in the bottom of the window."));
export const STATUS_BAR_ITEM_COMPACT_HOVER_BACKGROUND = registerColor('statusBarItem.compactHoverBackground', {
dark: Color.white.transparent(0.20),
light: Color.white.transparent(0.20),
hc: Color.white.transparent(0.20)
}, localize('statusBarItemCompactHoverBackground', "Status bar item background color when hovering an item that contains two hovers. The status bar is shown in the bottom of the window."));
export const STATUS_BAR_PROMINENT_ITEM_FOREGROUND = registerColor('statusBarItem.prominentForeground', {
dark: STATUS_BAR_FOREGROUND,
light: STATUS_BAR_FOREGROUND,

View file

@ -645,7 +645,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
case 'text':
text = iv.text;
break;
case 'variable':
case 'variable': {
let va = iv.variableName;
if (!va) {
const lineContent = model.getLineContent(iv.range.startLineNumber);
@ -656,7 +656,8 @@ export class DebugEditorContribution implements IDebugEditorContribution {
text = strings.format(var_value_format, va, value);
}
break;
case 'expression':
}
case 'expression': {
let expr = iv.expression;
if (!expr) {
const lineContent = model.getLineContent(iv.range.startLineNumber);
@ -670,6 +671,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
}
}
break;
}
}
if (text) {

View file

@ -86,12 +86,13 @@ export class LinkDetector {
case 'web':
container.appendChild(this.createWebLink(part.value));
break;
case 'path':
case 'path': {
const path = part.captures[0];
const lineNumber = part.captures[1] ? Number(part.captures[1]) : 0;
const columnNumber = part.captures[2] ? Number(part.captures[2]) : 0;
container.appendChild(this.createPathLink(part.value, path, lineNumber, columnNumber, workspaceFolder));
break;
}
}
} catch (e) {
container.appendChild(document.createTextNode(part.value));

View file

@ -164,7 +164,7 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter {
this.requestCallback(<DebugProtocol.Request>message);
}
break;
case 'response':
case 'response': {
const response = <DebugProtocol.Response>message;
const clb = this.pendingRequests.get(response.request_seq);
if (clb) {
@ -172,6 +172,7 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter {
clb(response);
}
break;
}
}
}
}

View file

@ -198,7 +198,7 @@ export function convertToVSCPaths(message: DebugProtocol.ProtocolMessage, toUri:
function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA: boolean, source: PathContainer | undefined) => void): void {
switch (msg.type) {
case 'event':
case 'event': {
const event = <DebugProtocol.Event>msg;
switch (event.event) {
case 'output':
@ -214,7 +214,8 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA:
break;
}
break;
case 'request':
}
case 'request': {
const request = <DebugProtocol.Request>msg;
switch (request.command) {
case 'setBreakpoints':
@ -236,7 +237,8 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA:
break;
}
break;
case 'response':
}
case 'response': {
const response = <DebugProtocol.Response>msg;
if (response.success && response.body) {
switch (response.command) {
@ -260,6 +262,7 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA:
}
}
break;
}
}
}

View file

@ -173,7 +173,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env?
}
break;
case ShellType.bash:
case ShellType.bash: {
quote = (s: string) => {
s = s.replace(/(["'\\\$])/g, '\\$1');
@ -203,6 +203,7 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env?
command += `${quote(a)} `;
}
break;
}
}
return command;

View file

@ -13,7 +13,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Verbosity, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities, IEditorIdentifier, GroupChangeKind } from 'vs/workbench/common/editor';
import { Verbosity, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities, IEditorIdentifier, GroupModelChangeKind } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions';
import { OpenEditorsFocusedContext, ExplorerFocusedContext, IFilesConfiguration, OpenEditor } from 'vs/workbench/contrib/files/common/files';
@ -138,7 +138,7 @@ export class OpenEditorsView extends ViewPane {
const groupDisposables = new Map<number, IDisposable>();
const addGroupListener = (group: IEditorGroup) => {
groupDisposables.set(group.id, group.onDidGroupChange(e => {
const groupModelChangeListener = group.onDidModelChange(e => {
if (this.listRefreshScheduler.isScheduled()) {
return;
}
@ -149,34 +149,31 @@ export class OpenEditorsView extends ViewPane {
const index = this.getIndex(group, e.editor);
switch (e.kind) {
case GroupChangeKind.GROUP_INDEX: {
case GroupModelChangeKind.EDITOR_ACTIVE:
case GroupModelChangeKind.GROUP_ACTIVE:
this.focusActiveEditor();
break;
case GroupModelChangeKind.GROUP_INDEX:
if (index >= 0) {
this.list.splice(index, 1, [group]);
}
break;
}
case GroupChangeKind.GROUP_ACTIVE:
case GroupChangeKind.EDITOR_ACTIVE: {
this.focusActiveEditor();
break;
}
case GroupChangeKind.EDITOR_DIRTY:
case GroupChangeKind.EDITOR_LABEL:
case GroupChangeKind.EDITOR_CAPABILITIES:
case GroupChangeKind.EDITOR_STICKY:
case GroupChangeKind.EDITOR_PIN: {
case GroupModelChangeKind.EDITOR_DIRTY:
case GroupModelChangeKind.EDITOR_STICKY:
case GroupModelChangeKind.EDITOR_CAPABILITIES:
case GroupModelChangeKind.EDITOR_PIN:
case GroupModelChangeKind.EDITOR_LABEL:
this.list.splice(index, 1, [new OpenEditor(e.editor!, group)]);
this.focusActiveEditor();
break;
}
case GroupChangeKind.EDITOR_OPEN:
case GroupChangeKind.EDITOR_CLOSE:
case GroupChangeKind.EDITOR_MOVE: {
case GroupModelChangeKind.EDITOR_OPEN:
case GroupModelChangeKind.EDITOR_MOVE:
case GroupModelChangeKind.EDITOR_CLOSE:
updateWholeList();
break;
}
}
}));
});
groupDisposables.set(group.id, groupModelChangeListener);
this._register(groupDisposables.get(group.id)!);
};

View file

@ -140,7 +140,7 @@ export class NotebookEditor extends EditorPane {
if (group) {
this._groupListener.clear();
this._groupListener.add(group.onWillCloseEditor(e => this._saveEditorViewState(e.editor)));
this._groupListener.add(group.onDidGroupChange(() => {
this._groupListener.add(group.onDidModelChange(() => {
if (this._editorGroupService.activeGroup !== group) {
this._widget?.value?.updateEditorFocus();
}

View file

@ -13,7 +13,7 @@ import { IBorrowValue, INotebookEditorService } from 'vs/workbench/contrib/noteb
import { INotebookEditor, INotebookEditorCreationOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { Emitter } from 'vs/base/common/event';
import { INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { GroupIdentifier, GroupChangeKind } from 'vs/workbench/common/editor';
import { GroupIdentifier } from 'vs/workbench/common/editor';
export class NotebookEditorWidgetService implements INotebookEditorService {
@ -40,9 +40,9 @@ export class NotebookEditorWidgetService implements INotebookEditorService {
const onNewGroup = (group: IEditorGroup) => {
const { id } = group;
const listeners: IDisposable[] = [];
listeners.push(group.onDidGroupChange(e => {
listeners.push(group.onDidCloseEditor(e => {
const widgets = this._borrowableEditors.get(group.id);
if (!widgets || e.kind !== GroupChangeKind.EDITOR_CLOSE) {
if (!widgets) {
return;
}

View file

@ -896,6 +896,12 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
this.view.triggerScrollFromMouseWheelEvent(browserEvent);
}
isElementAboveViewport(index: number) {
const elementTop = this.view.elementTop(index);
const elementBottom = elementTop + this.view.elementHeight(index);
return elementBottom < this.scrollTop;
}
updateElementHeight2(element: ICellViewModel, size: number): void {
const index = this._getViewIndexUpperBound(element);
@ -903,7 +909,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
return;
}
if (index < this.firstVisibleIndex) {
if (this.isElementAboveViewport(index)) {
// update element above viewport
const oldHeight = this.elementHeight(element);
const delta = oldHeight - size;

View file

@ -630,34 +630,33 @@ async function webviewPreloads(ctx: PreloadContext) {
}
break;
}
case 'preload':
case 'preload': {
const resources = event.data.resources;
for (const { uri, originalUri } of resources) {
kernelPreloads.load(uri, originalUri);
}
break;
}
case 'focus-output':
focusFirstFocusableInCell(event.data.cellId);
break;
case 'decorations':
{
let outputContainer = document.getElementById(event.data.cellId);
if (!outputContainer) {
viewModel.ensureOutputCell(event.data.cellId, -100000, true);
outputContainer = document.getElementById(event.data.cellId);
}
outputContainer?.classList.add(...event.data.addedClassNames);
outputContainer?.classList.remove(...event.data.removedClassNames);
case 'decorations': {
let outputContainer = document.getElementById(event.data.cellId);
if (!outputContainer) {
viewModel.ensureOutputCell(event.data.cellId, -100000, true);
outputContainer = document.getElementById(event.data.cellId);
}
outputContainer?.classList.add(...event.data.addedClassNames);
outputContainer?.classList.remove(...event.data.removedClassNames);
break;
}
case 'customKernelMessage':
onDidReceiveKernelMessage.fire(event.data.message);
break;
case 'customRendererMessage':
renderers.getRenderer(event.data.rendererId)?.receiveMessage(event.data.message);
break;
case 'notebookStyles':
case 'notebookStyles': {
const documentStyle = document.documentElement.style;
for (let i = documentStyle.length - 1; i >= 0; i--) {
@ -674,6 +673,7 @@ async function webviewPreloads(ctx: PreloadContext) {
documentStyle.setProperty(`--${name}`, value);
}
break;
}
case 'notebookOptions':
currentOptions = event.data.options;
viewModel.toggleDragDropEnabled(currentOptions.dragAndDropEnabled);

View file

@ -500,7 +500,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
case CellEditType.Replace:
this._replaceCells(edit.index, edit.count, edit.cells, synchronous, computeUndoRedo);
break;
case CellEditType.Output:
case CellEditType.Output: {
this._assertIndex(cellIndex);
const cell = this._cells[cellIndex];
if (edit.append) {
@ -509,6 +509,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this._spliceNotebookCellOutputs2(cell, edit.outputs.map(op => new NotebookCellOutputTextModel(op)), computeUndoRedo);
}
break;
}
case CellEditType.OutputItems:
{
this._assertIndex(cellIndex);

View file

@ -234,14 +234,14 @@ suite('NotebookCellList', () => {
assert.deepStrictEqual(cellList.scrollTop, 55);
assert.deepStrictEqual(cellList.getViewScrollBottom(), 265);
// cellList.updateElementHeight2(viewModel.cellAt(0)!, 50);
// assert.deepStrictEqual(cellList.scrollTop, 5);
// assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
cellList.updateElementHeight2(viewModel.cellAt(0)!, 50);
assert.deepStrictEqual(cellList.scrollTop, 5);
assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
// focus won't be visible after cell 0 grow to 250, so let's try to keep the focused cell visible
// cellList.updateElementHeight2(viewModel.cellAt(0)!, 250);
// assert.deepStrictEqual(cellList.scrollTop, 250 + 100 - cellList.renderHeight);
// assert.deepStrictEqual(cellList.getViewScrollBottom(), 250 + 100 - cellList.renderHeight + 210);
cellList.updateElementHeight2(viewModel.cellAt(0)!, 250);
assert.deepStrictEqual(cellList.scrollTop, 250 + 100 - cellList.renderHeight);
assert.deepStrictEqual(cellList.getViewScrollBottom(), 250 + 100 - cellList.renderHeight + 210);
});
});

View file

@ -294,7 +294,7 @@ export abstract class AbstractListSettingWidget<TDataItem extends object> extend
DOM.append(container, this.renderAddButton());
this.renderList();
this._register(DOM.addDisposableListener(this.listElement, DOM.EventType.CLICK, e => this.onListClick(e)));
this._register(DOM.addDisposableListener(this.listElement, DOM.EventType.POINTER_DOWN, e => this.onListClick(e)));
this._register(DOM.addDisposableListener(this.listElement, DOM.EventType.DBLCLICK, e => this.onListDoubleClick(e)));
this._register(DOM.addStandardDisposableListener(this.listElement, 'keydown', (e: StandardKeyboardEvent) => {
@ -447,7 +447,7 @@ export abstract class AbstractListSettingWidget<TDataItem extends object> extend
return rowElement;
}
private onListClick(e: MouseEvent): void {
private onListClick(e: PointerEvent): void {
const targetIdx = this.getClickedItemIndex(e);
if (targetIdx < 0) {
return;

View file

@ -264,12 +264,13 @@ class OnAutoForwardedAction extends Disposable {
break;
}
case OnPortForward.Silent: break;
default:
default: {
const elapsed = new Date().getTime() - this.lastNotifyTime.getTime();
this.logService.trace(`ForwardedPorts: (OnAutoForwardedAction) time elapsed since last notification ${elapsed} ms`);
if (elapsed > OnAutoForwardedAction.NOTIFY_COOL_DOWN) {
await this.showNotification(tunnel);
}
}
}
}
}

View file

@ -293,7 +293,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
case 'disconnected':
this.renderRemoteStatusIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from {0}", truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH))}`);
break;
default:
default: {
const tooltip = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
const hostNameTooltip = this.labelService.getHostTooltip(Schemas.vscodeRemote, this.remoteAuthority);
if (hostNameTooltip) {
@ -302,6 +302,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
tooltip.appendText(nls.localize({ key: 'host.tooltip', comment: ['{0} is a remote host name, e.g. Dev Container'] }, "Editing on {0}", hostLabel));
}
this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, tooltip);
}
}
return;
} else if (this.virtualWorkspaceLocation) {

View file

@ -675,12 +675,13 @@ export function searchMatchComparer(elementA: RenderableMatch, elementB: Rendera
return compareFileExtensions(elementA.name(), elementB.name());
case SearchSortOrder.FileNames:
return compareFileNames(elementA.name(), elementB.name());
case SearchSortOrder.Modified:
case SearchSortOrder.Modified: {
const fileStatA = elementA.fileStat;
const fileStatB = elementB.fileStat;
if (fileStatA && fileStatB) {
return fileStatB.mtime - fileStatA.mtime;
}
}
// Fall through otherwise
default:
return comparePaths(elementA.resource.fsPath, elementB.resource.fsPath) || compareFileNames(elementA.name(), elementB.name());

View file

@ -2162,7 +2162,7 @@ export function parseExitResult(
// Create exit code message
let message: string | undefined = undefined;
switch (typeof exitCodeOrError) {
case 'number':
case 'number': {
let commandLine: string | undefined = undefined;
if (shellLaunchConfig.executable) {
commandLine = shellLaunchConfig.executable;
@ -2187,7 +2187,8 @@ export function parseExitResult(
}
}
break;
case 'object':
}
case 'object': {
// Ignore internal errors
if (exitCodeOrError.message.toString().includes('Could not find pty with id')) {
break;
@ -2211,6 +2212,7 @@ export function parseExitResult(
}
message = nls.localize('launchFailed.errorMessage', "The terminal process failed to launch: {0}.", innerMessage);
break;
}
}
return { code, message };

View file

@ -844,7 +844,7 @@ export class PredictionTimeline {
const cursor = this.physicalCursor(buffer);
const beforeTestReaderIndex = reader.index;
switch (prediction.matches(reader, this._lookBehind)) {
case MatchResult.Success:
case MatchResult.Success: {
// if the input character matches what the next prediction expected, undo
// the prediction and write the real character out.
const eaten = input.slice(beforeTestReaderIndex, reader.index);
@ -859,13 +859,14 @@ export class PredictionTimeline {
this._lookBehind = prediction;
this._expected.shift();
break;
}
case MatchResult.Buffer:
// on a buffer, store the remaining data and completely read data
// to be output as normal.
this._inputBuffer = input.slice(beforeTestReaderIndex);
reader.index = input.length;
break ReadLoop;
case MatchResult.Failure:
case MatchResult.Failure: {
// on a failure, roll back all remaining items in this generation
// and clear predictions, since they are no longer valid
const rollback = this._expected.filter(p => p.gen === startingGen).reverse();
@ -878,6 +879,7 @@ export class PredictionTimeline {
this._clearPredictionState();
this._failedEmitter.fire(prediction);
break ReadLoop;
}
}
}
@ -1253,7 +1255,7 @@ class TypeAheadStyle implements IDisposable {
return { applyArgs: [4], undoArgs: [24] };
case 'inverted':
return { applyArgs: [7], undoArgs: [27] };
default:
default: {
let color: Color;
try {
color = Color.fromHex(style);
@ -1263,6 +1265,7 @@ class TypeAheadStyle implements IDisposable {
const { r, g, b } = color.rgba;
return { applyArgs: [38, 2, r, g, b], undoArgs: [39] };
}
}
}
}

View file

@ -15,9 +15,14 @@ class TestTerminalConfigHelper extends TerminalConfigHelper {
}
}
suite('Workbench - TerminalConfigHelper', () => {
suite('Workbench - TerminalConfigHelper', function () {
let fixture: HTMLElement;
// This suite has retries setup because the font-related tests flake only on GitHub actions, not
// ADO. It seems Electron hangs for some reason only on GH actions, so the two options are to
// retry or remove the test outright (which would drop coverage).
this.retries(3);
setup(() => {
fixture = document.body;
});

View file

@ -251,13 +251,13 @@ export class TestingPeekOpener extends Disposable implements ITestingPeekOpener
// don't show the peek if the user asked to only auto-open peeks for visible tests,
// and this test is not in any of the editors' models.
switch (cfg) {
case AutoOpenPeekViewWhen.FailureVisible:
case AutoOpenPeekViewWhen.FailureVisible: {
const editorUris = new Set(editors.map(e => e.getModel()?.uri.toString()));
if (!Iterable.some(resultItemParents(evt.result, evt.item), i => i.item.uri && editorUris.has(i.item.uri.toString()))) {
return;
}
break; //continue
}
case AutoOpenPeekViewWhen.FailureAnywhere:
break; //continue

View file

@ -164,7 +164,7 @@ export class SingleUseTestCollection extends Disposable {
}
break;
case ExtHostTestItemEventOp.SetProp:
case ExtHostTestItemEventOp.SetProp: {
const { key, value, previous } = evt;
const extId = internal.fullId.toString();
switch (key) {
@ -185,6 +185,7 @@ export class SingleUseTestCollection extends Disposable {
break;
}
break;
}
default:
assertNever(evt);
}

View file

@ -60,7 +60,7 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode
if (message?.type === TestMessageType.Error) { text = message.expected; }
break;
}
case TestUriType.ResultMessage:
case TestUriType.ResultMessage: {
const message = test.tasks[parsed.taskIndex].messages[parsed.messageIndex]?.message;
if (typeof message === 'string') {
text = message;
@ -69,6 +69,7 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode
language = this.languageService.createById('markdown');
}
break;
}
}
if (text === undefined) {

View file

@ -43,7 +43,7 @@ export const maxPriority = (...states: TestResultState[]) => {
return states[0];
case 2:
return statePriority[states[0]] > statePriority[states[1]] ? states[0] : states[1];
default:
default: {
let max = states[0];
for (let i = 1; i < states.length; i++) {
if (statePriority[max] < statePriority[states[i]]) {
@ -52,6 +52,7 @@ export const maxPriority = (...states: TestResultState[]) => {
}
return max;
}
}
};

View file

@ -118,7 +118,7 @@ export async function configureOpenerTrustedDomainsHandler(
options: { pinned: true }
});
return trustedDomains;
case 'trust':
case 'trust': {
const itemToTrust = pickedResult.toTrust;
if (trustedDomains.indexOf(itemToTrust) === -1) {
storageService.remove(TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, StorageScope.GLOBAL);
@ -131,6 +131,7 @@ export async function configureOpenerTrustedDomainsHandler(
return [...trustedDomains, itemToTrust];
}
}
}
}

View file

@ -27,7 +27,7 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben
private onAutoSyncError(error: UserDataSyncError): void {
switch (error.code) {
case UserDataSyncErrorCode.LocalTooManyRequests:
case UserDataSyncErrorCode.TooManyRequests:
case UserDataSyncErrorCode.TooManyRequests: {
const operationId = error.operationId ? localize('operationId', "Operation Id: {0}", error.operationId) : undefined;
const message = localize('too many requests', "Turned off syncing settings on this device because it is making too many requests.");
this.notificationService.notify({
@ -35,6 +35,7 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben
message: operationId ? `${message} ${operationId}` : message,
});
return;
}
}
}
}

View file

@ -59,6 +59,7 @@ import { EditorResolution } from 'vs/platform/editor/common/editor';
import { CATEGORIES } from 'vs/workbench/common/actions';
import { IUserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { IHostService } from 'vs/workbench/services/host/browser/host';
const CONTEXT_CONFLICTS_SOURCES = new RawContextKey<string>('conflictsSources', '');
@ -128,6 +129,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
@IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IUserDataInitializationService private readonly userDataInitializationService: IUserDataInitializationService,
@IHostService private readonly hostService: IHostService,
) {
super();
@ -333,7 +335,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
break;
case UserDataSyncErrorCode.IncompatibleLocalContent:
case UserDataSyncErrorCode.Gone:
case UserDataSyncErrorCode.UpgradeRequired:
case UserDataSyncErrorCode.UpgradeRequired: {
const message = localize('error upgrade required', "Settings sync is disabled because the current version ({0}, {1}) is not compatible with the sync service. Please update before turning on sync.", this.productService.version, this.productService.commit);
const operationId = error.operationId ? localize('operationId', "Operation Id: {0}", error.operationId) : undefined;
this.notificationService.notify({
@ -341,6 +343,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
message: operationId ? `${message} ${operationId}` : message,
});
break;
}
case UserDataSyncErrorCode.IncompatibleRemoteContent:
this.notificationService.notify({
severity: Severity.Error,
@ -407,12 +410,13 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
case UserDataSyncErrorCode.LocalInvalidContent:
this.handleInvalidContentError(source);
break;
default:
default: {
const disposable = this.invalidContentErrorDisposables.get(source);
if (disposable) {
disposable.dispose();
this.invalidContentErrorDisposables.delete(source);
}
}
}
}
} else {
@ -428,6 +432,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
if (source !== SyncResource.Settings && source !== SyncResource.Keybindings) {
return;
}
if (!this.hostService.hasFocus) {
return;
}
const resource = source === SyncResource.Settings ? this.environmentService.settingsResource : this.environmentService.keybindingsResource;
if (isEqual(resource, EditorResourceAccessor.getCanonicalUri(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }))) {
// Do not show notification if the file in error is active
@ -537,7 +544,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
break;
case UserDataSyncErrorCode.IncompatibleLocalContent:
case UserDataSyncErrorCode.Gone:
case UserDataSyncErrorCode.UpgradeRequired:
case UserDataSyncErrorCode.UpgradeRequired: {
const message = localize('error upgrade required while starting sync', "Settings sync cannot be turned on because the current version ({0}, {1}) is not compatible with the sync service. Please update before turning on sync.", this.productService.version, this.productService.commit);
const operationId = e.operationId ? localize('operationId', "Operation Id: {0}", e.operationId) : undefined;
this.notificationService.notify({
@ -545,6 +552,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
message: operationId ? `${message} ${operationId}` : message,
});
return;
}
case UserDataSyncErrorCode.IncompatibleRemoteContent:
this.notificationService.notify({
severity: Severity.Error,

View file

@ -47,7 +47,7 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben
private onAutoSyncError(error: UserDataSyncError): void {
switch (error.code) {
case UserDataSyncErrorCode.LocalTooManyRequests:
case UserDataSyncErrorCode.TooManyRequests:
case UserDataSyncErrorCode.TooManyRequests: {
const operationId = error.operationId ? localize('operationId', "Operation Id: {0}", error.operationId) : undefined;
const message = localize({ key: 'too many requests', comment: ['Settings Sync is the name of the feature'] }, "Settings sync is disabled because the current device is making too many requests. Please report an issue by providing the sync logs.");
this.notificationService.notify({
@ -62,6 +62,7 @@ class UserDataSyncReportIssueContribution extends Disposable implements IWorkben
}
});
return;
}
}
}
}

View file

@ -757,7 +757,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
}, this._fileService, this._logService, this._resourceLoadingCts.token);
switch (result.type) {
case WebviewResourceResponse.Type.Success:
case WebviewResourceResponse.Type.Success: {
const { buffer } = await streamToBuffer(result.stream);
return {
id,
@ -768,7 +768,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
etag: result.etag,
mtime: result.mtime
};
}
case WebviewResourceResponse.Type.NotModified:
return {
id,

View file

@ -191,7 +191,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
public isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {
switch (this.getWorkbenchState()) {
case WorkbenchState.FOLDER:
case WorkbenchState.FOLDER: {
let folderUri: URI | undefined = undefined;
if (URI.isUri(workspaceIdOrFolder)) {
folderUri = workspaceIdOrFolder;
@ -200,6 +200,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
}
return URI.isUri(folderUri) && this.uriIdentityService.extUri.isEqual(folderUri, this.workspace.folders[0].uri);
}
case WorkbenchState.WORKSPACE:
return isWorkspaceIdentifier(workspaceIdOrFolder) && this.workspace.id === workspaceIdOrFolder.id;
}
@ -353,11 +354,11 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
await this.reloadDefaultConfiguration();
return;
case ConfigurationTarget.USER:
case ConfigurationTarget.USER: {
const { local, remote } = await this.reloadUserConfiguration();
await this.loadConfiguration(local, remote);
return;
}
case ConfigurationTarget.USER_LOCAL:
await this.reloadLocalUserConfiguration();
return;
@ -901,11 +902,12 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
return this.reloadRemoteUserConfiguration().then(() => undefined);
case EditableConfigurationTarget.WORKSPACE:
return this.reloadWorkspaceConfiguration();
case EditableConfigurationTarget.WORKSPACE_FOLDER:
case EditableConfigurationTarget.WORKSPACE_FOLDER: {
const workspaceFolder = overrides && overrides.resource ? this.workspace.getFolder(overrides.resource) : null;
if (workspaceFolder) {
return this.reloadWorkspaceFolderConfiguration(workspaceFolder);
}
}
}
}

View file

@ -358,7 +358,7 @@ export class ConfigurationEditingService {
return nls.localize('errorInvalidRemoteConfiguration', "Unable to write into remote user settings. Please open the remote user settings to correct errors/warnings in it and try again.");
case EditableConfigurationTarget.WORKSPACE:
return nls.localize('errorInvalidConfigurationWorkspace', "Unable to write into workspace settings. Please open the workspace settings to correct errors/warnings in the file and try again.");
case EditableConfigurationTarget.WORKSPACE_FOLDER:
case EditableConfigurationTarget.WORKSPACE_FOLDER: {
let workspaceFolderName: string = '<<unknown>>';
if (operation.resource) {
const folder = this.contextService.getWorkspaceFolder(operation.resource);
@ -367,6 +367,7 @@ export class ConfigurationEditingService {
}
}
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName);
}
default:
return '';
}
@ -385,7 +386,7 @@ export class ConfigurationEditingService {
return nls.localize('errorRemoteConfigurationFileDirty', "Unable to write into remote user settings because the file has unsaved changes. Please save the remote user settings file first and then try again.");
case EditableConfigurationTarget.WORKSPACE:
return nls.localize('errorConfigurationFileDirtyWorkspace', "Unable to write into workspace settings because the file has unsaved changes. Please save the workspace settings file first and then try again.");
case EditableConfigurationTarget.WORKSPACE_FOLDER:
case EditableConfigurationTarget.WORKSPACE_FOLDER: {
let workspaceFolderName: string = '<<unknown>>';
if (operation.resource) {
const folder = this.contextService.getWorkspaceFolder(operation.resource);
@ -394,6 +395,7 @@ export class ConfigurationEditingService {
}
}
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file has unsaved changes. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName);
}
default:
return '';
}

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