Merge remote-tracking branch 'origin/main' into tyriar/137847

This commit is contained in:
Daniel Imms 2021-12-10 11:11:49 -08:00
commit da7ab25150
202 changed files with 2965 additions and 2308 deletions

View file

@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"December 2021\""
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"January 2022\""
},
{
"kind": 1,

View file

@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$inbox -label:\"needs more info\" sort:created-asc"
"value": "$inbox -label:\"needs more info\" sort:created-desc"
},
{
"kind": 1,

View file

@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github\n\n// current milestone name\n$milestone=milestone:\"December 2021\""
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github\n\n// current milestone name\n$milestone=milestone:\"January 2022\""
},
{
"kind": 1,

View file

@ -223,7 +223,7 @@ steps:
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME"
timeoutInMinutes: 10
displayName: Run smoke tests (Electron)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@ -233,7 +233,7 @@ steps:
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --remote --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --remote
timeoutInMinutes: 10
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))

View file

@ -214,7 +214,7 @@ steps:
- script: |
set -e
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
yarn smoketest-no-compile --build "$APP_PATH" --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
yarn smoketest-no-compile --build "$APP_PATH" --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader"
timeoutInMinutes: 10
displayName: Run smoke tests (Electron)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
@ -223,7 +223,7 @@ steps:
set -e
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
yarn smoketest-no-compile --build "$APP_PATH" --remote --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
yarn smoketest-no-compile --build "$APP_PATH" --remote --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader"
timeoutInMinutes: 10
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))

View file

@ -210,7 +210,7 @@ steps:
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --build "$AppRoot" --screenshots $(Build.SourcesDirectory)\.build\logs\smoke-tests }
exec { yarn smoketest-no-compile --build "$AppRoot" }
displayName: Run smoke tests (Electron)
timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
@ -220,7 +220,7 @@ steps:
$ErrorActionPreference = "Stop"
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"
exec { yarn smoketest-no-compile --build "$AppRoot" --remote --screenshots $(Build.SourcesDirectory)\.build\logs\smoke-tests-remote }
exec { yarn smoketest-no-compile --build "$AppRoot" --remote }
displayName: Run smoke tests (Remote)
timeoutInMinutes: 10
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))

View file

@ -1,7 +1,7 @@
{
"name": "monaco-editor-core",
"private": true,
"version": "0.31.0",
"version": "0.0.0",
"description": "A browser based code editor",
"author": "Microsoft Corporation",
"license": "MIT",

View file

@ -49,7 +49,7 @@
"commander": "^7.0.0",
"debug": "^4.3.2",
"electron-osx-sign": "^0.4.16",
"esbuild": "^0.12.6",
"esbuild": "^0.14.2",
"extract-zip": "^2.0.1",
"fs-extra": "^9.1.0",
"got": "11.8.1",

View file

@ -1336,10 +1336,113 @@ es6-error@^4.1.1:
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
esbuild@^0.12.6:
version "0.12.6"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.6.tgz#85bc755c7cf3005d4f34b4f10f98049ce0ee67ce"
integrity sha512-RDvVLvAjsq/kIZJoneMiUOH7EE7t2QaW7T3Q7EdQij14+bZbDq5sndb0tTanmHIFSqZVMBMMyqzVHkS3dJobeA==
esbuild-android-arm64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.2.tgz#256b7cf2f9d382a2a92a4ff4e13187587c9b7c6a"
integrity sha512-hEixaKMN3XXCkoe+0WcexO4CcBVU5DCSUT+7P8JZiWZCbAjSkc9b6Yz2X5DSfQmRCtI/cQRU6TfMYrMQ5NBfdw==
esbuild-darwin-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.2.tgz#891a59ce6bc3aded0265f982469b3eb9571b92f8"
integrity sha512-Uq8t0cbJQkxkQdbUfOl2wZqZ/AtLZjvJulR1HHnc96UgyzG9YlCLSDMiqjM+NANEy7/zzvwKJsy3iNC9wwqLJA==
esbuild-darwin-arm64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.2.tgz#ab834fffa9c612b2901ca1e77e4695d4d8aa63a2"
integrity sha512-619MSa17sr7YCIrUj88KzQu2ESA4jKYtIYfLU/smX6qNgxQt3Y/gzM4s6sgJ4fPQzirvmXgcHv1ZNQAs/Xh48A==
esbuild-freebsd-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.2.tgz#f7fc87a83f02de27d5a48472571efa1a432ae86d"
integrity sha512-aP6FE/ZsChZpUV6F3HE3x1Pz0paoYXycJ7oLt06g0G9dhJKknPawXCqQg/WMyD+ldCEZfo7F1kavenPdIT/SGQ==
esbuild-freebsd-arm64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.2.tgz#bc8758420431106751f3180293cac0b5bc4ce2ee"
integrity sha512-LSm98WTb1QIhyS83+Po0KTpZNdd2XpVpI9ua5rLWqKWbKeNRFwOsjeiuwBaRNc+O32s9oC2ZMefETxHBV6VNkQ==
esbuild-linux-32@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.2.tgz#0cc2dcd816d6d66e255bc7aeac139b1d04246812"
integrity sha512-8VxnNEyeUbiGflTKcuVc5JEPTqXfsx2O6ABwUbfS1Hp26lYPRPC7pKQK5Dxa0MBejGc50jy7YZae3EGQUQ8EkQ==
esbuild-linux-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.2.tgz#c790f739aa75b15c153609ea3457153fbe4db93d"
integrity sha512-4bzMS2dNxOJoFIiHId4w+tqQzdnsch71JJV1qZnbnErSFWcR9lRgpSqWnTTFtv6XM+MvltRzSXC5wQ7AEBY6Hg==
esbuild-linux-arm64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.2.tgz#96858a1f89ad30274dec780d0e3dd8b5691c6b0c"
integrity sha512-RlIVp0RwJrdtasDF1vTFueLYZ8WuFzxoQ1OoRFZOTyJHCGCNgh7xJIC34gd7B7+RT0CzLBB4LcM5n0LS+hIoww==
esbuild-linux-arm@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.2.tgz#03e193225afa9b1215d2ec6efe8edf0c03eeed6f"
integrity sha512-PaylahvMHhH8YMfJPMKEqi64qA0Su+d4FNfHKvlKes/2dUe4QxgbwXT9oLVgy8iJdcFMrO7By4R8fS8S0p8aVQ==
esbuild-linux-mips64le@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.2.tgz#972f218d2cb5125237376d40ad60a6e5356a782c"
integrity sha512-Fdwrq2roFnO5oetIiUQQueZ3+5soCxBSJswg3MvYaXDomj47BN6oAWMZgLrFh1oVrtWrxSDLCJBenYdbm2s+qQ==
esbuild-linux-ppc64le@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.2.tgz#20b71622ac09142b0e523f633af0829def7fed6b"
integrity sha512-vxptskw8JfCDD9QqpRO0XnsM1osuWeRjPaXX1TwdveLogYsbdFtcuiuK/4FxGiNMUr1ojtnCS2rMPbY8puc5NA==
esbuild-netbsd-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.2.tgz#dbd6a25117902ef67aa11d8779dd9c6bca7fbe82"
integrity sha512-I8+LzYK5iSNpspS9eCV9sW67Rj8FgMHimGri4mKiGAmN0pNfx+hFX146rYtzGtewuxKtTsPywWteHx+hPRLDsw==
esbuild-openbsd-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.2.tgz#3c5f199eed459b2f88865548394c0b77383d9ca4"
integrity sha512-120HgMe9elidWUvM2E6mMf0csrGwx8sYDqUIJugyMy1oHm+/nT08bTAVXuwYG/rkMIqsEO9AlMxuYnwR6En/3Q==
esbuild-sunos-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.2.tgz#900a681db6b76c6a7f60fc28d2bfe5b11698641c"
integrity sha512-Q3xcf9Uyfra9UuCFxoLixVvdigo0daZaKJ97TL2KNA4bxRUPK18wwGUk3AxvgDQZpRmg82w9PnkaNYo7a+24ow==
esbuild-windows-32@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.2.tgz#61e0ba5bd95b277a55d2b997ac4c04dfe2559220"
integrity sha512-TW7O49tPsrq+N1sW8mb3m24j/iDGa4xzAZH4wHWwoIzgtZAYPKC0hpIhufRRG/LA30bdMChO9pjJZ5mtcybtBQ==
esbuild-windows-64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.2.tgz#6ab59ef721ff75c682a1c8ae0570dabb637abddb"
integrity sha512-Rym6ViMNmi1E2QuQMWy0AFAfdY0wGwZD73BnzlsQBX5hZBuy/L+Speh7ucUZ16gwsrMM9v86icZUDrSN/lNBKg==
esbuild-windows-arm64@0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.2.tgz#aca2a4f83d2f0d1592ad4be832ed0045fc888cda"
integrity sha512-ZrLbhr0vX5Em/P1faMnHucjVVWPS+m3tktAtz93WkMZLmbRJevhiW1y4CbulBd2z0MEdXZ6emDa1zFHq5O5bSA==
esbuild@^0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.2.tgz#9c1e1a652549cc33e44885eea42ea2cc6267edc2"
integrity sha512-l076A6o/PIgcyM24s0dWmDI/b8RQf41uWoJu9I0M71CtW/YSw5T5NUeXxs5lo2tFQD+O4CW4nBHJXx3OY5NpXg==
optionalDependencies:
esbuild-android-arm64 "0.14.2"
esbuild-darwin-64 "0.14.2"
esbuild-darwin-arm64 "0.14.2"
esbuild-freebsd-64 "0.14.2"
esbuild-freebsd-arm64 "0.14.2"
esbuild-linux-32 "0.14.2"
esbuild-linux-64 "0.14.2"
esbuild-linux-arm "0.14.2"
esbuild-linux-arm64 "0.14.2"
esbuild-linux-mips64le "0.14.2"
esbuild-linux-ppc64le "0.14.2"
esbuild-netbsd-64 "0.14.2"
esbuild-openbsd-64 "0.14.2"
esbuild-sunos-64 "0.14.2"
esbuild-windows-32 "0.14.2"
esbuild-windows-64 "0.14.2"
esbuild-windows-arm64 "0.14.2"
escape-string-regexp@^1.0.5:
version "1.0.5"

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { window, InputBoxOptions, Uri, OutputChannel, Disposable, workspace } from 'vscode';
import { IDisposable, EmptyDisposable, toDisposable } from './util';
import { IDisposable, EmptyDisposable, toDisposable, logTimestamp } from './util';
import * as path from 'path';
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
import { CredentialsProvider, Credentials } from './api/git';
@ -19,7 +19,7 @@ export class Askpass implements IIPCHandler {
try {
return new Askpass(await createIPCServer(context));
} catch (err) {
outputChannel.appendLine(`[error] Failed to create git askpass IPC: ${err}`);
outputChannel.appendLine(`${logTimestamp()} [error] Failed to create git askpass IPC: ${err}`);
return new Askpass();
}
}

View file

@ -14,7 +14,7 @@ import { Model } from './model';
import { Repository, Resource, ResourceGroupType } from './repository';
import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
import { fromGitUri, toGitUri, isGitUri } from './uri';
import { grep, isDescendant, pathEquals } from './util';
import { grep, isDescendant, logTimestamp, pathEquals } from './util';
import { Log, LogLevel } from './log';
import { GitTimelineItem } from './timelineProvider';
import { ApiRepository } from './api/api1';
@ -353,7 +353,7 @@ export class CommandCenter {
}
Log.logLevel = choice.logLevel;
this.outputChannel.appendLine(localize('changed', "Log level changed to: {0}", LogLevel[Log.logLevel]));
this.outputChannel.appendLine(localize('changed', "{0} Log level changed to: {1}", logTimestamp(), LogLevel[Log.logLevel]));
}
@command('git.refresh', { repository: true })
@ -821,14 +821,14 @@ export class CommandCenter {
@command('git.stage')
async stage(...resourceStates: SourceControlResourceState[]): Promise<void> {
this.outputChannel.appendLine(`git.stage ${resourceStates.length}`);
this.outputChannel.appendLine(`${logTimestamp()} git.stage ${resourceStates.length}`);
resourceStates = resourceStates.filter(s => !!s);
if (resourceStates.length === 0 || (resourceStates[0] && !(resourceStates[0].resourceUri instanceof Uri))) {
const resource = this.getSCMResource();
this.outputChannel.appendLine(`git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null}`);
this.outputChannel.appendLine(`${logTimestamp()} git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null}`);
if (!resource) {
return;
@ -871,7 +871,7 @@ export class CommandCenter {
const untracked = selection.filter(s => s.resourceGroupType === ResourceGroupType.Untracked);
const scmResources = [...workingTree, ...untracked, ...resolved, ...unresolved];
this.outputChannel.appendLine(`git.stage.scmResources ${scmResources.length}`);
this.outputChannel.appendLine(`${logTimestamp()} git.stage.scmResources ${scmResources.length}`);
if (!scmResources.length) {
return;
}
@ -2878,10 +2878,10 @@ export class CommandCenter {
private getSCMResource(uri?: Uri): Resource | undefined {
uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri);
this.outputChannel.appendLine(`git.getSCMResource.uri ${uri && uri.toString()}`);
this.outputChannel.appendLine(`${logTimestamp()} git.getSCMResource.uri ${uri && uri.toString()}`);
for (const r of this.model.repositories.map(r => r.root)) {
this.outputChannel.appendLine(`repo root ${r}`);
this.outputChannel.appendLine(`${logTimestamp()} repo root ${r}`);
}
if (!uri) {

View file

@ -531,10 +531,15 @@ export class Git {
child.stdin!.end(options.input, 'utf8');
}
const startTime = Date.now();
const bufferResult = await exec(child, options.cancellationToken);
if (options.log !== false && bufferResult.stderr.length > 0) {
this.log(`${bufferResult.stderr}\n`);
if (options.log !== false) {
this.log(`> git ${args.join(' ')} [${Date.now() - startTime}ms]\n`);
if (bufferResult.stderr.length > 0) {
this.log(`${bufferResult.stderr}\n`);
}
}
let encoding = options.encoding || 'utf8';
@ -585,10 +590,6 @@ export class Git {
options.cwd = sanitizePath(options.cwd);
}
if (options.log !== false) {
this.log(`> git ${args.join(' ')}\n`);
}
return cp.spawn(this.path, args, options);
}

View file

@ -13,7 +13,7 @@ import { CommandCenter } from './commands';
import { GitFileSystemProvider } from './fileSystemProvider';
import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass';
import { toDisposable, filterEvent, eventToPromise } from './util';
import { toDisposable, filterEvent, eventToPromise, logTimestamp } from './util';
import TelemetryReporter from 'vscode-extension-telemetry';
import { GitExtension } from './api/git';
import { GitProtocolHandler } from './protocolHandler';
@ -46,7 +46,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
}
const info = await findGit(pathHints, gitPath => {
outputChannel.appendLine(localize('validating', "Validating found git in: {0}", gitPath));
outputChannel.appendLine(localize('validating', "{0} Validating found git in: {1}", logTimestamp(), gitPath));
if (excludes.length === 0) {
return true;
}
@ -54,7 +54,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
const normalized = path.normalize(gitPath).replace(/[\r\n]+$/, '');
const skip = excludes.some(e => normalized.startsWith(e));
if (skip) {
outputChannel.appendLine(localize('skipped', "Skipped found git in: {0}", gitPath));
outputChannel.appendLine(localize('skipped', "{0} Skipped found git in: {1}", logTimestamp(), gitPath));
}
return !skip;
});
@ -81,7 +81,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
model.onDidCloseRepository(onRepository, null, disposables);
onRepository();
outputChannel.appendLine(localize('using git', "Using git {0} from {1}", info.version, info.path));
outputChannel.appendLine(localize('using git', "{0} Using git {1} from {2}", logTimestamp(), info.version, info.path));
const onOutput = (str: string) => {
const lines = str.split(/\r?\n/mg);
@ -90,7 +90,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
lines.pop();
}
outputChannel.appendLine(lines.join('\n'));
outputChannel.appendLine(`${logTimestamp()} ${lines.join('\n')}`);
};
git.onOutput.addListener('log', onOutput);
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
@ -190,7 +190,7 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
}
console.warn(err.message);
outputChannel.appendLine(err.message);
outputChannel.appendLine(`${logTimestamp()} ${err.message}`);
commands.executeCommand('setContext', 'git.missing', true);
warnAboutMissingGit();

View file

@ -6,7 +6,7 @@
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel, commands } from 'vscode';
import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators';
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise } from './util';
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise, logTimestamp } from './util';
import { Git } from './git';
import * as path from 'path';
import * as fs from 'fs';
@ -146,7 +146,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
await Promise.all((workspace.workspaceFolders || []).map(async folder => {
const root = folder.uri.fsPath;
const children = await new Promise<string[]>((c, e) => fs.readdir(root, (err, r) => err ? e(err) : c(r)));
const children = (await fs.promises.readdir(root, { withFileTypes: true })).filter(dirent => dirent.isDirectory()).map(dirent => dirent.name);
const subfolders = new Set(children.filter(child => child !== '.git').map(child => path.join(root, child)));
const scanPaths = (workspace.isTrusted ? workspace.getConfiguration('git', folder.uri) : config).get<string[]>('scanRepositories') || [];
@ -303,7 +303,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
repository.status(); // do not await this, we want SCM to know about the repo asap
} catch (ex) {
// noop
this.outputChannel.appendLine(`Opening repository for path='${repoPath}' failed; ex=${ex}`);
this.outputChannel.appendLine(`${logTimestamp()} Opening repository for path='${repoPath}' failed; ex=${ex}`);
}
}
@ -329,7 +329,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
}
private open(repository: Repository): void {
this.outputChannel.appendLine(`Open repository: ${repository.root}`);
this.outputChannel.appendLine(`${logTimestamp()} Open repository: ${repository.root}`);
const onDidDisappearRepository = filterEvent(repository.onDidChangeState, state => state === RepositoryState.Disposed);
const disappearListener = onDidDisappearRepository(() => dispose());
@ -386,7 +386,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR
return;
}
this.outputChannel.appendLine(`Close repository: ${repository.root}`);
this.outputChannel.appendLine(`${logTimestamp()} Close repository: ${repository.root}`);
openRepository.dispose();
}

View file

@ -13,7 +13,7 @@ import { debounce, memoize, throttle } from './decorators';
import { Commit, GitError, Repository as BaseRepository, Stash, Submodule, LogFileOptions } from './git';
import { StatusBarCommands } from './statusbar';
import { toGitUri } from './uri';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, onceEvent } from './util';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, logTimestamp, onceEvent } from './util';
import { IFileWatcher, watch } from './watch';
import { Log, LogLevel } from './log';
import { IPushErrorHandlerRegistry } from './pushError';
@ -516,8 +516,8 @@ class FileEventLogger {
}
this.eventDisposable = combinedDisposable([
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`[debug] [wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`[debug] [.git] Change: ${uri.fsPath}`))
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [wt] Change: ${uri.fsPath}`)),
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [.git] Change: ${uri.fsPath}`))
]);
}
@ -567,7 +567,7 @@ class DotGitWatcher implements IFileWatcher {
upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables);
} catch (err) {
if (Log.logLevel <= LogLevel.Error) {
this.outputChannel.appendLine(`Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
this.outputChannel.appendLine(`${logTimestamp()} Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
}
}
}
@ -870,7 +870,7 @@ export class Repository implements Disposable {
this.disposables.push(dotGitFileWatcher);
} catch (err) {
if (Log.logLevel <= LogLevel.Error) {
outputChannel.appendLine(`Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
outputChannel.appendLine(`${logTimestamp()} Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
}
onDotGitFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => /\/\.git($|\/)/.test(uri.path));

View file

@ -13,6 +13,10 @@ export function log(...args: any[]): void {
console.log.apply(console, ['git:', ...args]);
}
export function logTimestamp(): string {
return `[${new Date().toISOString()}]`;
}
export interface IDisposable {
dispose(): void;
}

View file

@ -387,83 +387,152 @@ function convertRange(document: TextDocument, span: { start: number | undefined,
function convertKind(kind: string): CompletionItemKind {
switch (kind) {
case 'primitive type':
case 'keyword':
case Kind.primitiveType:
case Kind.keyword:
return CompletionItemKind.Keyword;
case 'var':
case 'local var':
return CompletionItemKind.Variable;
case 'property':
case 'getter':
case 'setter':
return CompletionItemKind.Field;
case 'function':
case 'method':
case 'construct':
case 'call':
case 'index':
return CompletionItemKind.Function;
case 'enum':
return CompletionItemKind.Enum;
case 'module':
return CompletionItemKind.Module;
case 'class':
return CompletionItemKind.Class;
case 'interface':
return CompletionItemKind.Interface;
case 'warning':
return CompletionItemKind.File;
}
return CompletionItemKind.Property;
case Kind.const:
case Kind.let:
case Kind.variable:
case Kind.localVariable:
case Kind.alias:
case Kind.parameter:
return CompletionItemKind.Variable;
case Kind.memberVariable:
case Kind.memberGetAccessor:
case Kind.memberSetAccessor:
return CompletionItemKind.Field;
case Kind.function:
case Kind.localFunction:
return CompletionItemKind.Function;
case Kind.method:
case Kind.constructSignature:
case Kind.callSignature:
case Kind.indexSignature:
return CompletionItemKind.Method;
case Kind.enum:
return CompletionItemKind.Enum;
case Kind.enumMember:
return CompletionItemKind.EnumMember;
case Kind.module:
case Kind.externalModuleName:
return CompletionItemKind.Module;
case Kind.class:
case Kind.type:
return CompletionItemKind.Class;
case Kind.interface:
return CompletionItemKind.Interface;
case Kind.warning:
return CompletionItemKind.Text;
case Kind.script:
return CompletionItemKind.File;
case Kind.directory:
return CompletionItemKind.Folder;
case Kind.string:
return CompletionItemKind.Constant;
default:
return CompletionItemKind.Property;
}
}
const enum Kind {
alias = 'alias',
callSignature = 'call',
class = 'class',
const = 'const',
constructorImplementation = 'constructor',
constructSignature = 'construct',
directory = 'directory',
enum = 'enum',
enumMember = 'enum member',
externalModuleName = 'external module name',
function = 'function',
indexSignature = 'index',
interface = 'interface',
keyword = 'keyword',
let = 'let',
localFunction = 'local function',
localVariable = 'local var',
method = 'method',
memberGetAccessor = 'getter',
memberSetAccessor = 'setter',
memberVariable = 'property',
module = 'module',
primitiveType = 'primitive type',
script = 'script',
type = 'type',
variable = 'var',
warning = 'warning',
string = 'string',
parameter = 'parameter',
typeParameter = 'type parameter'
}
function convertSymbolKind(kind: string): SymbolKind {
switch (kind) {
case 'var':
case 'local var':
case 'const':
return SymbolKind.Variable;
case 'function':
case 'local function':
return SymbolKind.Function;
case 'enum':
return SymbolKind.Enum;
case 'module':
return SymbolKind.Module;
case 'class':
return SymbolKind.Class;
case 'interface':
return SymbolKind.Interface;
case 'method':
return SymbolKind.Method;
case 'property':
case 'getter':
case 'setter':
return SymbolKind.Property;
case Kind.module: return SymbolKind.Module;
case Kind.class: return SymbolKind.Class;
case Kind.enum: return SymbolKind.Enum;
case Kind.enumMember: return SymbolKind.EnumMember;
case Kind.interface: return SymbolKind.Interface;
case Kind.indexSignature: return SymbolKind.Method;
case Kind.callSignature: return SymbolKind.Method;
case Kind.method: return SymbolKind.Method;
case Kind.memberVariable: return SymbolKind.Property;
case Kind.memberGetAccessor: return SymbolKind.Property;
case Kind.memberSetAccessor: return SymbolKind.Property;
case Kind.variable: return SymbolKind.Variable;
case Kind.let: return SymbolKind.Variable;
case Kind.const: return SymbolKind.Variable;
case Kind.localVariable: return SymbolKind.Variable;
case Kind.alias: return SymbolKind.Variable;
case Kind.function: return SymbolKind.Function;
case Kind.localFunction: return SymbolKind.Function;
case Kind.constructSignature: return SymbolKind.Constructor;
case Kind.constructorImplementation: return SymbolKind.Constructor;
case Kind.typeParameter: return SymbolKind.TypeParameter;
case Kind.string: return SymbolKind.String;
default: return SymbolKind.Variable;
}
return SymbolKind.Variable;
}
function convertOptions(options: FormattingOptions, formatSettings: any, initialIndentLevel: number): ts.FormatCodeOptions {
function convertOptions(options: FormattingOptions, formatSettings: any, initialIndentLevel: number): ts.FormatCodeSettings {
return {
ConvertTabsToSpaces: options.insertSpaces,
TabSize: options.tabSize,
IndentSize: options.tabSize,
IndentStyle: ts.IndentStyle.Smart,
NewLineCharacter: '\n',
BaseIndentSize: options.tabSize * initialIndentLevel,
InsertSpaceAfterCommaDelimiter: Boolean(!formatSettings || formatSettings.insertSpaceAfterCommaDelimiter),
InsertSpaceAfterSemicolonInForStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterSemicolonInForStatements),
InsertSpaceBeforeAndAfterBinaryOperators: Boolean(!formatSettings || formatSettings.insertSpaceBeforeAndAfterBinaryOperators),
InsertSpaceAfterKeywordsInControlFlowStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterKeywordsInControlFlowStatements),
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: Boolean(!formatSettings || formatSettings.insertSpaceAfterFunctionKeywordForAnonymousFunctions),
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis),
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets),
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces),
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces),
PlaceOpenBraceOnNewLineForControlBlocks: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForFunctions),
PlaceOpenBraceOnNewLineForFunctions: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForControlBlocks)
convertTabsToSpaces: options.insertSpaces,
tabSize: options.tabSize,
indentSize: options.tabSize,
indentStyle: ts.IndentStyle.Smart,
newLineCharacter: '\n',
baseIndentSize: options.tabSize * initialIndentLevel,
insertSpaceAfterCommaDelimiter: Boolean(!formatSettings || formatSettings.insertSpaceAfterCommaDelimiter),
insertSpaceAfterConstructor: Boolean(formatSettings && formatSettings.insertSpaceAfterConstructor),
insertSpaceAfterSemicolonInForStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterSemicolonInForStatements),
insertSpaceBeforeAndAfterBinaryOperators: Boolean(!formatSettings || formatSettings.insertSpaceBeforeAndAfterBinaryOperators),
insertSpaceAfterKeywordsInControlFlowStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterKeywordsInControlFlowStatements),
insertSpaceAfterFunctionKeywordForAnonymousFunctions: Boolean(!formatSettings || formatSettings.insertSpaceAfterFunctionKeywordForAnonymousFunctions),
insertSpaceBeforeFunctionParenthesis: Boolean(formatSettings && formatSettings.insertSpaceBeforeFunctionParenthesis),
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis),
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets),
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces),
insertSpaceAfterOpeningAndBeforeClosingEmptyBraces: Boolean(!formatSettings || formatSettings.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces),
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces),
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces),
insertSpaceAfterTypeAssertion: Boolean(formatSettings && formatSettings.insertSpaceAfterTypeAssertion),
placeOpenBraceOnNewLineForControlBlocks: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForFunctions),
placeOpenBraceOnNewLineForFunctions: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForControlBlocks),
semicolons: formatSettings?.semicolons
};
}

View file

@ -77,7 +77,7 @@ suite('HTML Embedded Formatting', () => {
});
test('HTML & Multiple Scripts', async () => {
await assertFormat('<html><head>\n<script>\nif(x){\nbar(); }\n</script><script>\nfunction(x){ }\n</script></head></html>', '<html>\n\n<head>\n <script>\n if (x) {\n bar();\n }\n </script>\n <script>\n function(x) {}\n </script>\n</head>\n\n</html>');
await assertFormat('<html><head>\n<script>\nif(x){\nbar(); }\n</script><script>\nfunction(x){ }\n</script></head></html>', '<html>\n\n<head>\n <script>\n if (x) {\n bar();\n }\n </script>\n <script>\n function(x) { }\n </script>\n</head>\n\n</html>');
});
test('HTML & Styles', async () => {
@ -120,7 +120,7 @@ suite('HTML Embedded Formatting', () => {
'<body>',
'',
' <script>',
' function f(x) {}',
' function f(x) { }',
' f(function () {',
' // ',
'',
@ -143,7 +143,7 @@ suite('HTML Embedded Formatting', () => {
'<body>',
'',
' <script>',
' function f(x) {}',
' function f(x) { }',
' f(function () {',
' // ',
'',

View file

@ -4,7 +4,7 @@
"license": "MIT",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "4.5"
"typescript": "4.5.3"
},
"scripts": {
"postinstall": "node ./postinstall"

View file

@ -7,7 +7,7 @@ import * as assert from 'assert';
import * as vscode from 'vscode';
import * as utils from '../utils';
suite.skip('Notebook Editor', function () {
suite('Notebook Editor', function () {
const contentSerializer = new class implements vscode.NotebookSerializer {
deserializeNotebook() {
@ -77,7 +77,8 @@ suite.skip('Notebook Editor', function () {
assert.strictEqual(editor2.viewColumn, vscode.ViewColumn.Two);
});
test('Opening a notebook should fire activeNotebook event changed only once', async function () {
// #138683
test.skip('Opening a notebook should fire activeNotebook event changed only once', async function () {
const openedEditor = utils.asPromise(vscode.window.onDidChangeActiveNotebookEditor);
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const editor = await vscode.window.showNotebookDocument(resource);

View file

@ -136,7 +136,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
}
};
suite.skip('Notebook API tests', function () {
suite('Notebook API tests', function () {
const testDisposables: vscode.Disposable[] = [];
const suiteDisposables: vscode.Disposable[] = [];
@ -872,7 +872,7 @@ suite.skip('Notebook API tests', function () {
});
});
suite.skip('statusbar', () => {
suite('statusbar', () => {
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
const onDidCallProvide = emitter.event;
const suiteDisposables: vscode.Disposable[] = [];
@ -910,7 +910,7 @@ suite.skip('statusbar', () => {
});
});
suite.skip('Notebook API tests (metadata)', function () {
suite('Notebook API tests (metadata)', function () {
const testDisposables: vscode.Disposable[] = [];
const suiteDisposables: vscode.Disposable[] = [];

View file

@ -24,10 +24,10 @@ fast-plist@0.1.2:
resolved "https://registry.yarnpkg.com/fast-plist/-/fast-plist-0.1.2.tgz#a45aff345196006d406ca6cdcd05f69051ef35b8"
integrity sha1-pFr/NFGWAG1AbKbNzQX2kFHvNbg=
typescript@4.5:
version "4.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998"
integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==
typescript@4.5.3:
version "4.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c"
integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==
vscode-grammar-updater@^1.0.3:
version "1.0.3"

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.63.0",
"distro": "28dea56425abcfafd4de9d5073e6fadfbf3518f5",
"version": "1.64.0",
"distro": "512d10b8c393921afc78cdfab44fd1633bc24aab",
"author": {
"name": "Microsoft Corporation"
},
@ -73,7 +73,7 @@
"keytar": "7.2.0",
"minimist": "^1.2.5",
"native-is-elevated": "0.4.3",
"native-keymap": "3.0.2",
"native-keymap": "3.0.3",
"native-watchdog": "1.3.0",
"node-pty": "0.11.0-beta11",
"spdlog": "^0.13.0",
@ -84,12 +84,12 @@
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
"vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm": "4.16.0-beta.5",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-serialize": "0.7.0-beta.3",
"xterm-addon-unicode11": "0.4.0-beta.1",
"xterm-addon-webgl": "0.12.0-beta.16",
"xterm-headless": "4.16.0-beta.2",
"xterm-headless": "4.16.0-beta.5",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},

View file

@ -23,12 +23,12 @@
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
"vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm": "4.16.0-beta.5",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-serialize": "0.7.0-beta.3",
"xterm-addon-unicode11": "0.4.0-beta.1",
"xterm-addon-webgl": "0.12.0-beta.16",
"xterm-headless": "4.16.0-beta.2",
"xterm-headless": "4.16.0-beta.5",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},

View file

@ -10,7 +10,7 @@
"tas-client-umd": "0.1.4",
"vscode-oniguruma": "1.6.1",
"vscode-textmate": "5.5.0",
"xterm": "4.16.0-beta.2",
"xterm": "4.16.0-beta.5",
"xterm-addon-search": "0.9.0-beta.6",
"xterm-addon-unicode11": "0.4.0-beta.1",
"xterm-addon-webgl": "0.12.0-beta.16"

View file

@ -128,7 +128,7 @@ xterm-addon-webgl@0.12.0-beta.16:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.16.tgz#63a0f1f5be9e66286e035448e2011e3065769ad5"
integrity sha512-g6v3RegOhSsD9Zt8ArWBMNT30QyPUlIWEIvP/xLHAluUZ1S5sDjFyZDB0nJAyn9MwQozJpwb0ylYO1nznN/TzA==
xterm@4.16.0-beta.2:
version "4.16.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.2.tgz#251beef21a232143f272da74c7005bc4d832ca79"
integrity sha512-PD0agueJ7qvbn1/QhZriAQXf+ykaoPKgQN9qiIGf88VMxHs8T47MYHW/+qPsrXagTmbrENtncughTIzOzv8Q5Q==
xterm@4.16.0-beta.5:
version "4.16.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.5.tgz#53ce503d76f718c90336766e6940fb1de81414a8"
integrity sha512-Nvodj6nbm4vf8f6nTaUw5Ll1PuPsjFuvVwkLg1VIis1bgrMVtgi5NyVQvDj0Mv804lzuys2FfKYeO/JJYy+RVA==

View file

@ -604,15 +604,15 @@ xterm-addon-webgl@0.12.0-beta.16:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.16.tgz#63a0f1f5be9e66286e035448e2011e3065769ad5"
integrity sha512-g6v3RegOhSsD9Zt8ArWBMNT30QyPUlIWEIvP/xLHAluUZ1S5sDjFyZDB0nJAyn9MwQozJpwb0ylYO1nznN/TzA==
xterm-headless@4.16.0-beta.2:
version "4.16.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.16.0-beta.2.tgz#62e66a655a30c814e3a311f3542d42c87446cecd"
integrity sha512-g92HDaIZcu1TQFlrjq2CHtt7A2qAwSD6s8RwncU/7u1kaq2e7rc9O3OKfu5v3QzgaRSKuugtquMr0OTKjkmLUg==
xterm-headless@4.16.0-beta.5:
version "4.16.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.16.0-beta.5.tgz#f805a2227b985939df0faa96e69fd245a7fa66e4"
integrity sha512-obbXZEwp02YY0EdHC3DM2V6j9O2O4M0yhcghcf6f5en0hattB5l/QZjhnJf+ogJ0SdCIh+VQRzqZ9BbKvGnGhw==
xterm@4.16.0-beta.2:
version "4.16.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.2.tgz#251beef21a232143f272da74c7005bc4d832ca79"
integrity sha512-PD0agueJ7qvbn1/QhZriAQXf+ykaoPKgQN9qiIGf88VMxHs8T47MYHW/+qPsrXagTmbrENtncughTIzOzv8Q5Q==
xterm@4.16.0-beta.5:
version "4.16.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.5.tgz#53ce503d76f718c90336766e6940fb1de81414a8"
integrity sha512-Nvodj6nbm4vf8f6nTaUw5Ll1PuPsjFuvVwkLg1VIis1bgrMVtgi5NyVQvDj0Mv804lzuys2FfKYeO/JJYy+RVA==
yauzl@^2.9.2:
version "2.10.0"

View file

@ -22,4 +22,4 @@
-ms-user-select: none;
}
/* icon rules are dynamically created in codiconStyles */
/* icon rules are dynamically created by the platform theme service (see iconsStyleSheet.ts) */

View file

@ -103,6 +103,8 @@ export class Menu extends ActionBar {
this.menuDisposables = this._register(new DisposableStore());
this.initializeOrUpdateStyleSheet(container, {});
this._register(Gesture.addTarget(menuElement));
addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
export interface IIconRegistry {
readonly all: IterableIterator<Codicon>;
@ -11,40 +11,6 @@ export interface IIconRegistry {
get(id: string): Codicon | undefined;
}
class Registry implements IIconRegistry {
private readonly _icons = new Map<string, Codicon>();
private readonly _onDidRegister = new Emitter<Codicon>();
public add(icon: Codicon) {
const existing = this._icons.get(icon.id);
if (!existing) {
this._icons.set(icon.id, icon);
this._onDidRegister.fire(icon);
} else if (icon.description) {
existing.description = icon.description;
} else {
console.error(`Duplicate registration of codicon ${icon.id}`);
}
}
public get(id: string): Codicon | undefined {
return this._icons.get(id);
}
public get all(): IterableIterator<Codicon> {
return this._icons.values();
}
public get onDidRegister(): Event<Codicon> {
return this._onDidRegister.event;
}
}
const _registry = new Registry();
export const iconRegistry: IIconRegistry = _registry;
// Selects all codicon names encapsulated in the `$()` syntax and wraps the
// results with spaces so that screen readers can read the text better.
export function getCodiconAriaLabel(text: string | undefined) {
@ -59,18 +25,28 @@ export function getCodiconAriaLabel(text: string | undefined) {
* The Codicon library is a set of default icons that are built-in in VS Code.
*
* In the product (outside of base) Codicons should only be used as defaults. In order to have all icons in VS Code
* themeable, component should ise define new, component specific icons using `iconRegistry.registerIcon`.
* In that call a Codicon can be names as default.
* themeable, component should define new, UI component specific icons using `iconRegistry.registerIcon`.
* In that call a Codicon can be named as default.
*/
export class Codicon implements CSSIcon {
private constructor(public readonly id: string, public readonly definition: IconDefinition, public description?: string) {
_registry.add(this);
Codicon._allCodicons.push(this);
}
public get classNames() { return 'codicon codicon-' + this.id; }
// classNamesArray is useful for migrating to ES6 classlist
public get classNamesArray() { return ['codicon', 'codicon-' + this.id]; }
public get cssSelector() { return '.codicon.codicon-' + this.id; }
// registry
private static _allCodicons : Codicon[] = [];
/**
* @returns Returns all default icons covered by the codicon font. Only to be used by the icon registry in platform.
*/
public static getAll() : readonly Codicon[] {
return Codicon._allCodicons;
}
// built-in icons, with image name
public static readonly add = new Codicon('add', { fontCharacter: '\\ea60' });
@ -402,6 +378,7 @@ export class Codicon implements CSSIcon {
public static readonly starHalf = new Codicon('star-half', { fontCharacter: '\\eb5a' });
public static readonly symbolClass = new Codicon('symbol-class', { fontCharacter: '\\eb5b' });
public static readonly symbolColor = new Codicon('symbol-color', { fontCharacter: '\\eb5c' });
public static readonly symbolCustomColor = new Codicon('symbol-customcolor', { fontCharacter: '\\eb5c' });
public static readonly symbolConstant = new Codicon('symbol-constant', { fontCharacter: '\\eb5d' });
public static readonly symbolEnumMember = new Codicon('symbol-enum-member', { fontCharacter: '\\eb5e' });
public static readonly symbolField = new Codicon('symbol-field', { fontCharacter: '\\eb5f' });

View file

@ -147,8 +147,13 @@ export class HistoryNavigator2<T> {
}
}
replaceLast(value: T): void {
/**
* @returns old last value
*/
replaceLast(value: T): T {
const oldValue = this.tail.value;
this.tail.value = value;
return oldValue;
}
isAtEnd(): boolean {

View file

@ -202,6 +202,19 @@ export function format(documentText: string, range: Range | undefined, options:
return editOperations;
}
/**
* Creates a formatted string out of the object passed as argument, using the given formatting options
* @param any The object to stringify and format
* @param options The formatting options to use
*/
export function toFormattedString(obj: any, options: FormattingOptions) {
const content = JSON.stringify(obj, undefined, options.insertSpaces ? options.tabSize || 4 : '\t');
if (options.eol !== undefined) {
return content.replace(/\r\n|\r|\n/g, options.eol);
}
return content;
}
function repeat(s: string, count: number): string {
let result = '';
for (let i = 0; i < count; i++) {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from 'vs/base/common/errors';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
/**
* The payload that flows in readable stream events.
@ -558,14 +558,31 @@ export interface IStreamListener<T> {
/**
* Helper to listen to all events of a T stream in proper order.
*/
export function listenStream<T>(stream: ReadableStreamEvents<T>, listener: IStreamListener<T>): void {
stream.on('error', error => listener.onError(error));
stream.on('end', () => listener.onEnd());
export function listenStream<T>(stream: ReadableStreamEvents<T>, listener: IStreamListener<T>): IDisposable {
let destroyed = false;
stream.on('error', error => {
if (!destroyed) {
listener.onError(error);
}
});
stream.on('end', () => {
if (!destroyed) {
listener.onEnd();
}
});
// Adding the `data` listener will turn the stream
// into flowing mode. As such it is important to
// add this listener last (DO NOT CHANGE!)
stream.on('data', data => listener.onData(data));
stream.on('data', data => {
if (!destroyed) {
listener.onData(data);
}
});
return toDisposable(() => destroyed = true);
}
/**

View file

@ -438,4 +438,33 @@ suite('JSON - formatter', () => {
format(content, expected);
});
test('toFormattedString', () => {
const obj = {
a: { b: 1, d: ['hello'] }
};
const getExpected = (tab: string, eol: string) => {
return [
`{`,
`${tab}"a": {`,
`${tab}${tab}"b": 1,`,
`${tab}${tab}"d": [`,
`${tab}${tab}${tab}"hello"`,
`${tab}${tab}]`,
`${tab}}`,
'}'
].join(eol);
};
let actual = Formatter.toFormattedString(obj, { insertSpaces: true, tabSize: 2, eol: '\n' });
assert.strictEqual(actual, getExpected(' ', '\n'));
actual = Formatter.toFormattedString(obj, { insertSpaces: true, tabSize: 2, eol: '\r\n' });
assert.strictEqual(actual, getExpected(' ', '\r\n'));
actual = Formatter.toFormattedString(obj, { insertSpaces: false, eol: '\r\n' });
assert.strictEqual(actual, getExpected('\t', '\r\n'));
});
});

View file

@ -343,6 +343,40 @@ suite('Stream', () => {
assert.strictEqual(end, true);
});
test('listenStream - dispose', () => {
const stream = newWriteableStream<string>(strings => strings.join());
let error = false;
let end = false;
let data = '';
const disposable = listenStream(stream, {
onData: d => {
data = d;
},
onError: e => {
error = true;
},
onEnd: () => {
end = true;
}
});
disposable.dispose();
stream.write('Hello');
assert.strictEqual(data, '');
stream.write('World');
assert.strictEqual(data, '');
stream.error(new Error());
assert.strictEqual(error, false);
stream.end('Final Bit');
assert.strictEqual(end, false);
});
test('peekStream', async () => {
for (let i = 0; i < 5; i++) {
const stream = readableToStream(arrayToReadable(['1', '2', '3', '4', '5']));

View file

@ -56,6 +56,7 @@ import { DOMLineBreaksComputerFactory } from 'vs/editor/browser/view/domLineBrea
import { WordOperations } from 'vs/editor/common/controller/cursorWordOperations';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { OutgoingViewModelEventKind } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
let EDITOR_ID = 0;
@ -256,7 +257,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService,
@IAccessibilityService accessibilityService: IAccessibilityService
@IAccessibilityService accessibilityService: IAccessibilityService,
@ILanguageConfigurationService private readonly languageConfigurationService: ILanguageConfigurationService,
) {
super();
@ -1525,7 +1527,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
model,
DOMLineBreaksComputerFactory.create(),
MonospaceLineBreaksComputerFactory.create(this._configuration.options),
(callback) => dom.scheduleAtNextAnimationFrame(callback)
(callback) => dom.scheduleAtNextAnimationFrame(callback),
this.languageConfigurationService
);
listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));

View file

@ -19,6 +19,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
@ -35,9 +36,10 @@ export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService,
@IAccessibilityService accessibilityService: IAccessibilityService
@IAccessibilityService accessibilityService: IAccessibilityService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
) {
super(domElement, { ...parentEditor.getRawOptions(), overflowWidgetsDomNode: parentEditor.getOverflowWidgetsDomNode() }, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService);
super(domElement, { ...parentEditor.getRawOptions(), overflowWidgetsDomNode: parentEditor.getOverflowWidgetsDomNode() }, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService);
this._parentEditor = parentEditor;
this._overwriteOptions = options;

View file

@ -21,104 +21,6 @@ import { dispose, Disposable } from 'vs/base/common/lifecycle';
import { ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';
import { CursorStateChangedEvent, ViewModelEventsCollector } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
/**
* A snapshot of the cursor and the model state
*/
export class CursorModelState {
public readonly modelVersionId: number;
public readonly cursorState: CursorState[];
constructor(model: ITextModel, cursor: CursorsController) {
this.modelVersionId = model.getVersionId();
this.cursorState = cursor.getCursorStates();
}
public equals(other: CursorModelState | null): boolean {
if (!other) {
return false;
}
if (this.modelVersionId !== other.modelVersionId) {
return false;
}
if (this.cursorState.length !== other.cursorState.length) {
return false;
}
for (let i = 0, len = this.cursorState.length; i < len; i++) {
if (!this.cursorState[i].equals(other.cursorState[i])) {
return false;
}
}
return true;
}
}
class AutoClosedAction {
public static getAllAutoClosedCharacters(autoClosedActions: AutoClosedAction[]): Range[] {
let autoClosedCharacters: Range[] = [];
for (const autoClosedAction of autoClosedActions) {
autoClosedCharacters = autoClosedCharacters.concat(autoClosedAction.getAutoClosedCharactersRanges());
}
return autoClosedCharacters;
}
private readonly _model: ITextModel;
private _autoClosedCharactersDecorations: string[];
private _autoClosedEnclosingDecorations: string[];
constructor(model: ITextModel, autoClosedCharactersDecorations: string[], autoClosedEnclosingDecorations: string[]) {
this._model = model;
this._autoClosedCharactersDecorations = autoClosedCharactersDecorations;
this._autoClosedEnclosingDecorations = autoClosedEnclosingDecorations;
}
public dispose(): void {
this._autoClosedCharactersDecorations = this._model.deltaDecorations(this._autoClosedCharactersDecorations, []);
this._autoClosedEnclosingDecorations = this._model.deltaDecorations(this._autoClosedEnclosingDecorations, []);
}
public getAutoClosedCharactersRanges(): Range[] {
let result: Range[] = [];
for (let i = 0; i < this._autoClosedCharactersDecorations.length; i++) {
const decorationRange = this._model.getDecorationRange(this._autoClosedCharactersDecorations[i]);
if (decorationRange) {
result.push(decorationRange);
}
}
return result;
}
public isValid(selections: Range[]): boolean {
let enclosingRanges: Range[] = [];
for (let i = 0; i < this._autoClosedEnclosingDecorations.length; i++) {
const decorationRange = this._model.getDecorationRange(this._autoClosedEnclosingDecorations[i]);
if (decorationRange) {
enclosingRanges.push(decorationRange);
if (decorationRange.startLineNumber !== decorationRange.endLineNumber) {
// Stop tracking if the range becomes multiline...
return false;
}
}
}
enclosingRanges.sort(Range.compareRangesUsingStarts);
selections.sort(Range.compareRangesUsingStarts);
for (let i = 0; i < selections.length; i++) {
if (i >= enclosingRanges.length) {
return false;
}
if (!enclosingRanges[i].strictContainsRange(selections[i])) {
return false;
}
}
return true;
}
}
export class CursorsController extends Disposable {
public static readonly MAX_CURSOR_COUNT = 10000;
@ -221,7 +123,7 @@ export class CursorsController extends Disposable {
reachedMaxCursorCount = true;
}
const oldState = new CursorModelState(this._model, this);
const oldState = CursorModelState.from(this._model, this);
this._cursors.setStates(states);
this._cursors.normalize();
@ -505,7 +407,7 @@ export class CursorsController extends Disposable {
// ----- emitting events
private _emitStateChangedIfNecessary(eventsCollector: ViewModelEventsCollector, source: string | null | undefined, reason: CursorChangeReason, oldState: CursorModelState | null, reachedMaxCursorCount: boolean): boolean {
const newState = new CursorModelState(this._model, this);
const newState = CursorModelState.from(this._model, this);
if (newState.equals(oldState)) {
return false;
}
@ -616,7 +518,7 @@ export class CursorsController extends Disposable {
return;
}
const oldState = new CursorModelState(this._model, this);
const oldState = CursorModelState.from(this._model, this);
this._cursors.stopTrackingSelections();
this._isHandling = true;
@ -731,6 +633,105 @@ export class CursorsController extends Disposable {
}
}
/**
* A snapshot of the cursor and the model state
*/
class CursorModelState {
public static from(model: ITextModel, cursor: CursorsController): CursorModelState {
return new CursorModelState(model.getVersionId(), cursor.getCursorStates());
}
constructor(
public readonly modelVersionId: number,
public readonly cursorState: CursorState[],
) {
}
public equals(other: CursorModelState | null): boolean {
if (!other) {
return false;
}
if (this.modelVersionId !== other.modelVersionId) {
return false;
}
if (this.cursorState.length !== other.cursorState.length) {
return false;
}
for (let i = 0, len = this.cursorState.length; i < len; i++) {
if (!this.cursorState[i].equals(other.cursorState[i])) {
return false;
}
}
return true;
}
}
class AutoClosedAction {
public static getAllAutoClosedCharacters(autoClosedActions: AutoClosedAction[]): Range[] {
let autoClosedCharacters: Range[] = [];
for (const autoClosedAction of autoClosedActions) {
autoClosedCharacters = autoClosedCharacters.concat(autoClosedAction.getAutoClosedCharactersRanges());
}
return autoClosedCharacters;
}
private readonly _model: ITextModel;
private _autoClosedCharactersDecorations: string[];
private _autoClosedEnclosingDecorations: string[];
constructor(model: ITextModel, autoClosedCharactersDecorations: string[], autoClosedEnclosingDecorations: string[]) {
this._model = model;
this._autoClosedCharactersDecorations = autoClosedCharactersDecorations;
this._autoClosedEnclosingDecorations = autoClosedEnclosingDecorations;
}
public dispose(): void {
this._autoClosedCharactersDecorations = this._model.deltaDecorations(this._autoClosedCharactersDecorations, []);
this._autoClosedEnclosingDecorations = this._model.deltaDecorations(this._autoClosedEnclosingDecorations, []);
}
public getAutoClosedCharactersRanges(): Range[] {
let result: Range[] = [];
for (let i = 0; i < this._autoClosedCharactersDecorations.length; i++) {
const decorationRange = this._model.getDecorationRange(this._autoClosedCharactersDecorations[i]);
if (decorationRange) {
result.push(decorationRange);
}
}
return result;
}
public isValid(selections: Range[]): boolean {
let enclosingRanges: Range[] = [];
for (let i = 0; i < this._autoClosedEnclosingDecorations.length; i++) {
const decorationRange = this._model.getDecorationRange(this._autoClosedEnclosingDecorations[i]);
if (decorationRange) {
enclosingRanges.push(decorationRange);
if (decorationRange.startLineNumber !== decorationRange.endLineNumber) {
// Stop tracking if the range becomes multiline...
return false;
}
}
}
enclosingRanges.sort(Range.compareRangesUsingStarts);
selections.sort(Range.compareRangesUsingStarts);
for (let i = 0; i < selections.length; i++) {
if (i >= enclosingRanges.length) {
return false;
}
if (!enclosingRanges[i].strictContainsRange(selections[i])) {
return false;
}
}
return true;
}
}
interface IExecContext {
readonly model: ITextModel;
readonly selectionsBefore: Selection[];

View file

@ -7,15 +7,6 @@ import { CursorColumns, CursorConfiguration, ICursorSimpleModel, SingleCursorSta
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
export interface IColumnSelectResult {
viewStates: SingleCursorState[];
reversed: boolean;
fromLineNumber: number;
fromVisualColumn: number;
toLineNumber: number;
toVisualColumn: number;
}
export class ColumnSelection {
public static columnSelect(config: CursorConfiguration, model: ICursorSimpleModel, fromLineNumber: number, fromVisibleColumn: number, toLineNumber: number, toVisibleColumn: number): IColumnSelectResult {
@ -124,3 +115,12 @@ export class ColumnSelection {
return this.columnSelect(config, model, prevColumnSelectData.fromViewLineNumber, prevColumnSelectData.fromViewVisualColumn, toViewLineNumber, prevColumnSelectData.toViewVisualColumn);
}
}
export interface IColumnSelectResult {
viewStates: SingleCursorState[];
reversed: boolean;
fromLineNumber: number;
fromVisualColumn: number;
toLineNumber: number;
toVisualColumn: number;
}

View file

@ -3,16 +3,18 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from 'vs/base/common/errors';
import { ConfigurationChangedEvent, EditorAutoClosingEditStrategy, EditorAutoClosingStrategy, EditorAutoIndentStrategy, EditorAutoSurroundStrategy, EditorOption } from 'vs/editor/common/config/editorOptions';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { ICommand, IConfiguration } from 'vs/editor/common/editorCommon';
import { ITextModel, PositionAffinity, TextModelResolvedOptions } from 'vs/editor/common/model';
import { TextModel } from 'vs/editor/common/model/textModel';
import { AutoClosingPairs, IAutoClosingPair } from 'vs/editor/common/modes/languageConfiguration';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { AutoClosingPairs } from 'vs/editor/common/modes/languageConfiguration';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { createScopedLineTokens } from 'vs/editor/common/modes/supports';
import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';
export { CursorColumns } from './cursorColumns';
@ -104,7 +106,8 @@ export class CursorConfiguration {
constructor(
languageId: string,
modelOptions: TextModelResolvedOptions,
configuration: IConfiguration
configuration: IConfiguration,
private readonly languageConfigurationService: ILanguageConfigurationService
) {
this._languageId = languageId;
@ -135,13 +138,13 @@ export class CursorConfiguration {
this._electricChars = null;
this.shouldAutoCloseBefore = {
quote: CursorConfiguration._getShouldAutoClose(languageId, this.autoClosingQuotes),
bracket: CursorConfiguration._getShouldAutoClose(languageId, this.autoClosingBrackets)
quote: this._getShouldAutoClose(languageId, this.autoClosingQuotes),
bracket: this._getShouldAutoClose(languageId, this.autoClosingBrackets)
};
this.autoClosingPairs = LanguageConfigurationRegistry.getAutoClosingPairs(languageId);
this.autoClosingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoClosingPairs();
let surroundingPairs = CursorConfiguration._getSurroundingPairs(languageId);
let surroundingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getSurroundingPairs();
if (surroundingPairs) {
for (const pair of surroundingPairs) {
this.surroundingPairs[pair.open] = pair.close;
@ -152,7 +155,7 @@ export class CursorConfiguration {
public get electricChars() {
if (!this._electricChars) {
this._electricChars = {};
let electricChars = CursorConfiguration._getElectricCharacters(this._languageId);
const electricChars = this.languageConfigurationService.getLanguageConfiguration(this._languageId).electricCharacter?.getElectricCharacters();
if (electricChars) {
for (const char of electricChars) {
this._electricChars[char] = true;
@ -162,25 +165,28 @@ export class CursorConfiguration {
return this._electricChars;
}
/**
* Should return opening bracket type to match indentation with
*/
public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction | null {
let scopedLineTokens = createScopedLineTokens(context, column - 1);
let electricCharacterSupport = this.languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).electricCharacter;
if (!electricCharacterSupport) {
return null;
}
return electricCharacterSupport.onElectricCharacter(character, scopedLineTokens, column - scopedLineTokens.firstCharOffset);
}
public normalizeIndentation(str: string): string {
return TextModel.normalizeIndentation(str, this.indentSize, this.insertSpaces);
}
private static _getElectricCharacters(languageId: string): string[] | null {
try {
return LanguageConfigurationRegistry.getElectricCharacters(languageId);
} catch (e) {
onUnexpectedError(e);
return null;
}
}
private static _getShouldAutoClose(languageId: string, autoCloseConfig: EditorAutoClosingStrategy): (ch: string) => boolean {
private _getShouldAutoClose(languageId: string, autoCloseConfig: EditorAutoClosingStrategy): (ch: string) => boolean {
switch (autoCloseConfig) {
case 'beforeWhitespace':
return autoCloseBeforeWhitespace;
case 'languageDefined':
return CursorConfiguration._getLanguageDefinedShouldAutoClose(languageId);
return this._getLanguageDefinedShouldAutoClose(languageId);
case 'always':
return autoCloseAlways;
case 'never':
@ -188,23 +194,9 @@ export class CursorConfiguration {
}
}
private static _getLanguageDefinedShouldAutoClose(languageId: string): (ch: string) => boolean {
try {
const autoCloseBeforeSet = LanguageConfigurationRegistry.getAutoCloseBeforeSet(languageId);
return c => autoCloseBeforeSet.indexOf(c) !== -1;
} catch (e) {
onUnexpectedError(e);
return autoCloseNever;
}
}
private static _getSurroundingPairs(languageId: string): IAutoClosingPair[] | null {
try {
return LanguageConfigurationRegistry.getSurroundingPairs(languageId);
} catch (e) {
onUnexpectedError(e);
return null;
}
private _getLanguageDefinedShouldAutoClose(languageId: string): (ch: string) => boolean {
const autoCloseBeforeSet = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoCloseBeforeSet();
return c => autoCloseBeforeSet.indexOf(c) !== -1;
}
}
@ -227,6 +219,86 @@ export interface ICursorSimpleModel {
getLineIndentColumn(lineNumber: number): number;
}
export class CursorContext {
_cursorContextBrand: void = undefined;
public readonly model: ITextModel;
public readonly viewModel: ICursorSimpleModel;
public readonly coordinatesConverter: ICoordinatesConverter;
public readonly cursorConfig: CursorConfiguration;
constructor(model: ITextModel, viewModel: ICursorSimpleModel, coordinatesConverter: ICoordinatesConverter, cursorConfig: CursorConfiguration) {
this.model = model;
this.viewModel = viewModel;
this.coordinatesConverter = coordinatesConverter;
this.cursorConfig = cursorConfig;
}
}
export type PartialCursorState = CursorState | PartialModelCursorState | PartialViewCursorState;
export class CursorState {
_cursorStateBrand: void = undefined;
public static fromModelState(modelState: SingleCursorState): PartialModelCursorState {
return new PartialModelCursorState(modelState);
}
public static fromViewState(viewState: SingleCursorState): PartialViewCursorState {
return new PartialViewCursorState(viewState);
}
public static fromModelSelection(modelSelection: ISelection): PartialModelCursorState {
const selection = Selection.liftSelection(modelSelection);
const modelState = new SingleCursorState(
Range.fromPositions(selection.getSelectionStart()),
0,
selection.getPosition(), 0
);
return CursorState.fromModelState(modelState);
}
public static fromModelSelections(modelSelections: readonly ISelection[]): PartialModelCursorState[] {
let states: PartialModelCursorState[] = [];
for (let i = 0, len = modelSelections.length; i < len; i++) {
states[i] = this.fromModelSelection(modelSelections[i]);
}
return states;
}
readonly modelState: SingleCursorState;
readonly viewState: SingleCursorState;
constructor(modelState: SingleCursorState, viewState: SingleCursorState) {
this.modelState = modelState;
this.viewState = viewState;
}
public equals(other: CursorState): boolean {
return (this.viewState.equals(other.viewState) && this.modelState.equals(other.modelState));
}
}
export class PartialModelCursorState {
readonly modelState: SingleCursorState;
readonly viewState: null;
constructor(modelState: SingleCursorState) {
this.modelState = modelState;
this.viewState = null;
}
}
export class PartialViewCursorState {
readonly modelState: null;
readonly viewState: SingleCursorState;
constructor(viewState: SingleCursorState) {
this.modelState = null;
this.viewState = viewState;
}
}
/**
* Represents the cursor state on either the model or on the view model.
*/
@ -295,86 +367,6 @@ export class SingleCursorState {
}
}
export class CursorContext {
_cursorContextBrand: void = undefined;
public readonly model: ITextModel;
public readonly viewModel: ICursorSimpleModel;
public readonly coordinatesConverter: ICoordinatesConverter;
public readonly cursorConfig: CursorConfiguration;
constructor(model: ITextModel, viewModel: ICursorSimpleModel, coordinatesConverter: ICoordinatesConverter, cursorConfig: CursorConfiguration) {
this.model = model;
this.viewModel = viewModel;
this.coordinatesConverter = coordinatesConverter;
this.cursorConfig = cursorConfig;
}
}
export class PartialModelCursorState {
readonly modelState: SingleCursorState;
readonly viewState: null;
constructor(modelState: SingleCursorState) {
this.modelState = modelState;
this.viewState = null;
}
}
export class PartialViewCursorState {
readonly modelState: null;
readonly viewState: SingleCursorState;
constructor(viewState: SingleCursorState) {
this.modelState = null;
this.viewState = viewState;
}
}
export type PartialCursorState = CursorState | PartialModelCursorState | PartialViewCursorState;
export class CursorState {
_cursorStateBrand: void = undefined;
public static fromModelState(modelState: SingleCursorState): PartialModelCursorState {
return new PartialModelCursorState(modelState);
}
public static fromViewState(viewState: SingleCursorState): PartialViewCursorState {
return new PartialViewCursorState(viewState);
}
public static fromModelSelection(modelSelection: ISelection): PartialModelCursorState {
const selection = Selection.liftSelection(modelSelection);
const modelState = new SingleCursorState(
Range.fromPositions(selection.getSelectionStart()),
0,
selection.getPosition(), 0
);
return CursorState.fromModelState(modelState);
}
public static fromModelSelections(modelSelections: readonly ISelection[]): PartialModelCursorState[] {
let states: PartialModelCursorState[] = [];
for (let i = 0, len = modelSelections.length; i < len; i++) {
states[i] = this.fromModelSelection(modelSelections[i]);
}
return states;
}
readonly modelState: SingleCursorState;
readonly viewState: SingleCursorState;
constructor(modelState: SingleCursorState, viewState: SingleCursorState) {
this.modelState = modelState;
this.viewState = viewState;
}
public equals(other: CursorState): boolean {
return (this.viewState.equals(other.viewState) && this.modelState.equals(other.modelState));
}
}
export class EditOperationResult {
_editOperationResultBrand: void = undefined;

View file

@ -773,7 +773,7 @@ export class TypeOperations {
let electricAction: IElectricAction | null;
try {
electricAction = LanguageConfigurationRegistry.onElectricCharacter(ch, lineTokens, position.column);
electricAction = config.onElectricCharacter(ch, lineTokens, position.column);
} catch (e) {
onUnexpectedError(e);
return null;

View file

@ -18,7 +18,7 @@ import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureR
import { TokenizationRegistryImpl } from 'vs/editor/common/modes/tokenizationRegistry';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { iconRegistry, Codicon } from 'vs/base/common/codicons';
import { Codicon, CSSIcon } from 'vs/base/common/codicons';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
/**
* Open ended enum at runtime
@ -371,94 +371,102 @@ export const enum CompletionItemKind {
/**
* @internal
*/
export const completionKindToCssClass = (function () {
let data = Object.create(null);
data[CompletionItemKind.Method] = 'symbol-method';
data[CompletionItemKind.Function] = 'symbol-function';
data[CompletionItemKind.Constructor] = 'symbol-constructor';
data[CompletionItemKind.Field] = 'symbol-field';
data[CompletionItemKind.Variable] = 'symbol-variable';
data[CompletionItemKind.Class] = 'symbol-class';
data[CompletionItemKind.Struct] = 'symbol-struct';
data[CompletionItemKind.Interface] = 'symbol-interface';
data[CompletionItemKind.Module] = 'symbol-module';
data[CompletionItemKind.Property] = 'symbol-property';
data[CompletionItemKind.Event] = 'symbol-event';
data[CompletionItemKind.Operator] = 'symbol-operator';
data[CompletionItemKind.Unit] = 'symbol-unit';
data[CompletionItemKind.Value] = 'symbol-value';
data[CompletionItemKind.Constant] = 'symbol-constant';
data[CompletionItemKind.Enum] = 'symbol-enum';
data[CompletionItemKind.EnumMember] = 'symbol-enum-member';
data[CompletionItemKind.Keyword] = 'symbol-keyword';
data[CompletionItemKind.Snippet] = 'symbol-snippet';
data[CompletionItemKind.Text] = 'symbol-text';
data[CompletionItemKind.Color] = 'symbol-color';
data[CompletionItemKind.File] = 'symbol-file';
data[CompletionItemKind.Reference] = 'symbol-reference';
data[CompletionItemKind.Customcolor] = 'symbol-customcolor';
data[CompletionItemKind.Folder] = 'symbol-folder';
data[CompletionItemKind.TypeParameter] = 'symbol-type-parameter';
data[CompletionItemKind.User] = 'account';
data[CompletionItemKind.Issue] = 'issues';
export namespace CompletionItemKinds {
return function (kind: CompletionItemKind): string {
const name = data[kind];
let codicon = name && iconRegistry.get(name);
const byKind = new Map<CompletionItemKind, CSSIcon>();
byKind.set(CompletionItemKind.Method, Codicon.symbolMethod);
byKind.set(CompletionItemKind.Function, Codicon.symbolFunction);
byKind.set(CompletionItemKind.Constructor, Codicon.symbolConstructor);
byKind.set(CompletionItemKind.Field, Codicon.symbolField);
byKind.set(CompletionItemKind.Variable, Codicon.symbolVariable);
byKind.set(CompletionItemKind.Class, Codicon.symbolClass);
byKind.set(CompletionItemKind.Struct, Codicon.symbolStruct);
byKind.set(CompletionItemKind.Interface, Codicon.symbolInterface);
byKind.set(CompletionItemKind.Module, Codicon.symbolModule);
byKind.set(CompletionItemKind.Property, Codicon.symbolProperty);
byKind.set(CompletionItemKind.Event, Codicon.symbolEvent);
byKind.set(CompletionItemKind.Operator, Codicon.symbolOperator);
byKind.set(CompletionItemKind.Unit, Codicon.symbolUnit);
byKind.set(CompletionItemKind.Value, Codicon.symbolValue);
byKind.set(CompletionItemKind.Enum, Codicon.symbolEnum);
byKind.set(CompletionItemKind.Constant, Codicon.symbolConstant);
byKind.set(CompletionItemKind.Enum, Codicon.symbolEnum);
byKind.set(CompletionItemKind.EnumMember, Codicon.symbolEnumMember);
byKind.set(CompletionItemKind.Keyword, Codicon.symbolKeyword);
byKind.set(CompletionItemKind.Snippet, Codicon.symbolSnippet);
byKind.set(CompletionItemKind.Text, Codicon.symbolText);
byKind.set(CompletionItemKind.Color, Codicon.symbolColor);
byKind.set(CompletionItemKind.File, Codicon.symbolFile);
byKind.set(CompletionItemKind.Reference, Codicon.symbolReference);
byKind.set(CompletionItemKind.Customcolor, Codicon.symbolCustomColor);
byKind.set(CompletionItemKind.Folder, Codicon.symbolFolder);
byKind.set(CompletionItemKind.TypeParameter, Codicon.symbolTypeParameter);
byKind.set(CompletionItemKind.User, Codicon.account);
byKind.set(CompletionItemKind.Issue, Codicon.issues);
/**
* @internal
*/
export function toIcon(kind: CompletionItemKind): CSSIcon {
let codicon = byKind.get(kind);
if (!codicon) {
console.info('No codicon found for CompletionItemKind ' + kind);
codicon = Codicon.symbolProperty;
}
return codicon.classNames;
};
})();
return codicon;
}
/**
* @internal
*/
export let completionKindFromString: {
(value: string): CompletionItemKind;
(value: string, strict: true): CompletionItemKind | undefined;
} = (function () {
let data: Record<string, CompletionItemKind> = Object.create(null);
data['method'] = CompletionItemKind.Method;
data['function'] = CompletionItemKind.Function;
data['constructor'] = <any>CompletionItemKind.Constructor;
data['field'] = CompletionItemKind.Field;
data['variable'] = CompletionItemKind.Variable;
data['class'] = CompletionItemKind.Class;
data['struct'] = CompletionItemKind.Struct;
data['interface'] = CompletionItemKind.Interface;
data['module'] = CompletionItemKind.Module;
data['property'] = CompletionItemKind.Property;
data['event'] = CompletionItemKind.Event;
data['operator'] = CompletionItemKind.Operator;
data['unit'] = CompletionItemKind.Unit;
data['value'] = CompletionItemKind.Value;
data['constant'] = CompletionItemKind.Constant;
data['enum'] = CompletionItemKind.Enum;
data['enum-member'] = CompletionItemKind.EnumMember;
data['enumMember'] = CompletionItemKind.EnumMember;
data['keyword'] = CompletionItemKind.Keyword;
data['snippet'] = CompletionItemKind.Snippet;
data['text'] = CompletionItemKind.Text;
data['color'] = CompletionItemKind.Color;
data['file'] = CompletionItemKind.File;
data['reference'] = CompletionItemKind.Reference;
data['customcolor'] = CompletionItemKind.Customcolor;
data['folder'] = CompletionItemKind.Folder;
data['type-parameter'] = CompletionItemKind.TypeParameter;
data['typeParameter'] = CompletionItemKind.TypeParameter;
data['account'] = CompletionItemKind.User;
data['issue'] = CompletionItemKind.Issue;
return function (value: string, strict?: true) {
let res = data[value];
const data = new Map<string, CompletionItemKind>();
data.set('method', CompletionItemKind.Method);
data.set('function', CompletionItemKind.Function);
data.set('constructor', <any>CompletionItemKind.Constructor);
data.set('field', CompletionItemKind.Field);
data.set('variable', CompletionItemKind.Variable);
data.set('class', CompletionItemKind.Class);
data.set('struct', CompletionItemKind.Struct);
data.set('interface', CompletionItemKind.Interface);
data.set('module', CompletionItemKind.Module);
data.set('property', CompletionItemKind.Property);
data.set('event', CompletionItemKind.Event);
data.set('operator', CompletionItemKind.Operator);
data.set('unit', CompletionItemKind.Unit);
data.set('value', CompletionItemKind.Value);
data.set('constant', CompletionItemKind.Constant);
data.set('enum', CompletionItemKind.Enum);
data.set('enum-member', CompletionItemKind.EnumMember);
data.set('enumMember', CompletionItemKind.EnumMember);
data.set('keyword', CompletionItemKind.Keyword);
data.set('snippet', CompletionItemKind.Snippet);
data.set('text', CompletionItemKind.Text);
data.set('color', CompletionItemKind.Color);
data.set('file', CompletionItemKind.File);
data.set('reference', CompletionItemKind.Reference);
data.set('customcolor', CompletionItemKind.Customcolor);
data.set('folder', CompletionItemKind.Folder);
data.set('type-parameter', CompletionItemKind.TypeParameter);
data.set('typeParameter', CompletionItemKind.TypeParameter);
data.set('account', CompletionItemKind.User);
data.set('issue', CompletionItemKind.Issue);
/**
* @internal
*/
export function fromString(value: string): CompletionItemKind;
/**
* @internal
*/
export function fromString(value: string, strict: true): CompletionItemKind | undefined;
/**
* @internal
*/
export function fromString(value: string, strict?: boolean): CompletionItemKind | undefined {
let res = data.get(value);
if (typeof res === 'undefined' && !strict) {
res = CompletionItemKind.Property;
}
return res;
};
})();
}
}
export interface CompletionItemLabel {
label: string;
@ -1103,84 +1111,43 @@ export const enum SymbolTag {
*/
export namespace SymbolKinds {
const byName = new Map<string, SymbolKind>();
byName.set('file', SymbolKind.File);
byName.set('module', SymbolKind.Module);
byName.set('namespace', SymbolKind.Namespace);
byName.set('package', SymbolKind.Package);
byName.set('class', SymbolKind.Class);
byName.set('method', SymbolKind.Method);
byName.set('property', SymbolKind.Property);
byName.set('field', SymbolKind.Field);
byName.set('constructor', SymbolKind.Constructor);
byName.set('enum', SymbolKind.Enum);
byName.set('interface', SymbolKind.Interface);
byName.set('function', SymbolKind.Function);
byName.set('variable', SymbolKind.Variable);
byName.set('constant', SymbolKind.Constant);
byName.set('string', SymbolKind.String);
byName.set('number', SymbolKind.Number);
byName.set('boolean', SymbolKind.Boolean);
byName.set('array', SymbolKind.Array);
byName.set('object', SymbolKind.Object);
byName.set('key', SymbolKind.Key);
byName.set('null', SymbolKind.Null);
byName.set('enum-member', SymbolKind.EnumMember);
byName.set('struct', SymbolKind.Struct);
byName.set('event', SymbolKind.Event);
byName.set('operator', SymbolKind.Operator);
byName.set('type-parameter', SymbolKind.TypeParameter);
const byKind = new Map<SymbolKind, string>();
byKind.set(SymbolKind.File, 'file');
byKind.set(SymbolKind.Module, 'module');
byKind.set(SymbolKind.Namespace, 'namespace');
byKind.set(SymbolKind.Package, 'package');
byKind.set(SymbolKind.Class, 'class');
byKind.set(SymbolKind.Method, 'method');
byKind.set(SymbolKind.Property, 'property');
byKind.set(SymbolKind.Field, 'field');
byKind.set(SymbolKind.Constructor, 'constructor');
byKind.set(SymbolKind.Enum, 'enum');
byKind.set(SymbolKind.Interface, 'interface');
byKind.set(SymbolKind.Function, 'function');
byKind.set(SymbolKind.Variable, 'variable');
byKind.set(SymbolKind.Constant, 'constant');
byKind.set(SymbolKind.String, 'string');
byKind.set(SymbolKind.Number, 'number');
byKind.set(SymbolKind.Boolean, 'boolean');
byKind.set(SymbolKind.Array, 'array');
byKind.set(SymbolKind.Object, 'object');
byKind.set(SymbolKind.Key, 'key');
byKind.set(SymbolKind.Null, 'null');
byKind.set(SymbolKind.EnumMember, 'enum-member');
byKind.set(SymbolKind.Struct, 'struct');
byKind.set(SymbolKind.Event, 'event');
byKind.set(SymbolKind.Operator, 'operator');
byKind.set(SymbolKind.TypeParameter, 'type-parameter');
const byKind = new Map<SymbolKind, CSSIcon>();
byKind.set(SymbolKind.File, Codicon.symbolFile);
byKind.set(SymbolKind.Module, Codicon.symbolModule);
byKind.set(SymbolKind.Namespace, Codicon.symbolNamespace);
byKind.set(SymbolKind.Package, Codicon.symbolPackage);
byKind.set(SymbolKind.Class, Codicon.symbolClass);
byKind.set(SymbolKind.Method, Codicon.symbolMethod);
byKind.set(SymbolKind.Property, Codicon.symbolProperty);
byKind.set(SymbolKind.Field, Codicon.symbolField);
byKind.set(SymbolKind.Constructor, Codicon.symbolConstructor);
byKind.set(SymbolKind.Enum, Codicon.symbolEnum);
byKind.set(SymbolKind.Interface, Codicon.symbolInterface);
byKind.set(SymbolKind.Function, Codicon.symbolFunction);
byKind.set(SymbolKind.Variable, Codicon.symbolVariable);
byKind.set(SymbolKind.Constant, Codicon.symbolConstant);
byKind.set(SymbolKind.String, Codicon.symbolString);
byKind.set(SymbolKind.Number, Codicon.symbolNumber);
byKind.set(SymbolKind.Boolean, Codicon.symbolBoolean);
byKind.set(SymbolKind.Array, Codicon.symbolArray);
byKind.set(SymbolKind.Object, Codicon.symbolObject);
byKind.set(SymbolKind.Key, Codicon.symbolKey);
byKind.set(SymbolKind.Null, Codicon.symbolNull);
byKind.set(SymbolKind.EnumMember, Codicon.symbolEnumMember);
byKind.set(SymbolKind.Struct, Codicon.symbolStruct);
byKind.set(SymbolKind.Event, Codicon.symbolEvent);
byKind.set(SymbolKind.Operator, Codicon.symbolOperator);
byKind.set(SymbolKind.TypeParameter, Codicon.symbolTypeParameter);
/**
* @internal
*/
export function fromString(value: string): SymbolKind | undefined {
return byName.get(value);
}
/**
* @internal
*/
export function toString(kind: SymbolKind): string | undefined {
return byKind.get(kind);
}
/**
* @internal
*/
export function toCssClassName(kind: SymbolKind, inline?: boolean): string {
const symbolName = byKind.get(kind);
let codicon = symbolName && iconRegistry.get('symbol-' + symbolName);
if (!codicon) {
export function toIcon(kind: SymbolKind): CSSIcon {
let icon = byKind.get(kind);
if (!icon) {
console.info('No codicon found for SymbolKind ' + kind);
codicon = Codicon.symbolProperty;
icon = Codicon.symbolProperty;
}
return `${inline ? 'inline' : 'block'} ${codicon.classNames}`;
return icon;
}
}

View file

@ -13,7 +13,7 @@ import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common
import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, CompleteEnterAction, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration';
import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports';
import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair';
import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { BracketElectricCharacterSupport } from 'vs/editor/common/modes/supports/electricCharacter';
import { IndentConsts, IndentRulesSupport } from 'vs/editor/common/modes/supports/indentRules';
import { OnEnterSupport } from 'vs/editor/common/modes/supports/onEnter';
import { RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
@ -204,38 +204,6 @@ export class LanguageConfigurationRegistryImpl {
return entries?.getResolvedConfiguration() || null;
}
// begin electricCharacter
private _getElectricCharacterSupport(languageId: string): BracketElectricCharacterSupport | null {
let value = this.getLanguageConfiguration(languageId);
if (!value) {
return null;
}
return value.electricCharacter || null;
}
public getElectricCharacters(languageId: string): string[] {
let electricCharacterSupport = this._getElectricCharacterSupport(languageId);
if (!electricCharacterSupport) {
return [];
}
return electricCharacterSupport.getElectricCharacters();
}
/**
* Should return opening bracket type to match indentation with
*/
public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction | null {
let scopedLineTokens = createScopedLineTokens(context, column - 1);
let electricCharacterSupport = this._getElectricCharacterSupport(scopedLineTokens.languageId);
if (!electricCharacterSupport) {
return null;
}
return electricCharacterSupport.onElectricCharacter(character, scopedLineTokens, column - scopedLineTokens.firstCharOffset);
}
// end electricCharacter
public getComments(languageId: string): ICommentsConfiguration | null {
let value = this.getLanguageConfiguration(languageId);
if (!value) {
@ -244,66 +212,6 @@ export class LanguageConfigurationRegistryImpl {
return value.comments || null;
}
// begin characterPair
private _getCharacterPairSupport(languageId: string): CharacterPairSupport | null {
let value = this.getLanguageConfiguration(languageId);
if (!value) {
return null;
}
return value.characterPair || null;
}
public getAutoClosingPairs(languageId: string): AutoClosingPairs {
const characterPairSupport = this._getCharacterPairSupport(languageId);
return new AutoClosingPairs(characterPairSupport ? characterPairSupport.getAutoClosingPairs() : []);
}
public getAutoCloseBeforeSet(languageId: string): string {
let characterPairSupport = this._getCharacterPairSupport(languageId);
if (!characterPairSupport) {
return CharacterPairSupport.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED;
}
return characterPairSupport.getAutoCloseBeforeSet();
}
public getSurroundingPairs(languageId: string): IAutoClosingPair[] {
let characterPairSupport = this._getCharacterPairSupport(languageId);
if (!characterPairSupport) {
return [];
}
return characterPairSupport.getSurroundingPairs();
}
// end characterPair
public getWordDefinition(languageId: string): RegExp {
let value = this.getLanguageConfiguration(languageId);
if (!value) {
return ensureValidWordDefinition(null);
}
return ensureValidWordDefinition(value.wordDefinition || null);
}
public getWordDefinitions(): [string, RegExp][] {
let result: [string, RegExp][] = [];
for (const [language, entries] of this._entries) {
const value = entries.getResolvedConfiguration();
if (value) {
result.push([language, value.wordDefinition]);
}
}
return result;
}
public getFoldingRules(languageId: string): FoldingRules {
let value = this.getLanguageConfiguration(languageId);
if (!value) {
return {};
}
return value.foldingRules;
}
// begin Indent Rules
public getIndentRulesSupport(languageId: string): IndentRulesSupport | null {
@ -967,11 +875,6 @@ export class ResolvedLanguageConfiguration {
return this._electricCharacter;
}
public getAutoClosingPairs(): AutoClosingPairs {
const characterPairSupport = this.characterPair;
return new AutoClosingPairs(characterPairSupport ? characterPairSupport.getAutoClosingPairs() : []);
}
public onEnter(
autoIndent: EditorAutoIndentStrategy,
previousLineText: string,
@ -989,6 +892,18 @@ export class ResolvedLanguageConfiguration {
);
}
public getAutoClosingPairs(): AutoClosingPairs {
return new AutoClosingPairs(this.characterPair.getAutoClosingPairs());
}
public getAutoCloseBeforeSet(): string {
return this.characterPair.getAutoCloseBeforeSet();
}
public getSurroundingPairs(): IAutoClosingPair[] {
return this.characterPair.getSurroundingPairs();
}
private static _handleComments(
conf: LanguageConfiguration
): ICommentsConfiguration | null {

View file

@ -13,7 +13,7 @@ import { IRange, Range } from 'vs/editor/common/core/range';
import { IChange } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker';
import { IDiffComputationResult, IEditorWorkerService, IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorkerService';
import { IModelService } from 'vs/editor/common/services/modelService';
@ -57,11 +57,12 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker
constructor(
@IModelService modelService: IModelService,
@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,
@ILogService logService: ILogService
@ILogService logService: ILogService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
) {
super();
this._modelService = modelService;
this._workerManager = this._register(new WorkerManager(this._modelService));
this._workerManager = this._register(new WorkerManager(this._modelService, languageConfigurationService));
this._logService = logService;
// register default link-provider and default completions-provider
@ -75,7 +76,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker
});
}
}));
this._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService)));
this._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService, languageConfigurationService)));
}
public override dispose(): void {
@ -145,7 +146,8 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider {
constructor(
workerManager: WorkerManager,
configurationService: ITextResourceConfigurationService,
modelService: IModelService
modelService: IModelService,
private readonly languageConfigurationService: ILanguageConfigurationService
) {
this._workerManager = workerManager;
this._configurationService = configurationService;
@ -187,7 +189,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider {
return undefined; // File too large, no other files
}
const wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId());
const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();
const word = model.getWordAtPosition(position);
const replace = !word ? Range.fromPositions(position) : new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
const insert = replace.setEndPosition(position.lineNumber, position.column);
@ -218,7 +220,7 @@ class WorkerManager extends Disposable {
private _editorWorkerClient: EditorWorkerClient | null;
private _lastWorkerUsedTime: number;
constructor(modelService: IModelService) {
constructor(modelService: IModelService, private readonly languageConfigurationService: ILanguageConfigurationService) {
super();
this._modelService = modelService;
this._editorWorkerClient = null;
@ -272,7 +274,7 @@ class WorkerManager extends Disposable {
public withWorker(): Promise<EditorWorkerClient> {
this._lastWorkerUsedTime = (new Date()).getTime();
if (!this._editorWorkerClient) {
this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService');
this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService', this.languageConfigurationService);
}
return Promise.resolve(this._editorWorkerClient);
}
@ -420,7 +422,12 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
private _modelManager: EditorModelManager | null;
private _disposed = false;
constructor(modelService: IModelService, keepIdleModels: boolean, label: string | undefined) {
constructor(
modelService: IModelService,
keepIdleModels: boolean,
label: string | undefined,
private readonly languageConfigurationService: ILanguageConfigurationService
) {
super();
this._modelService = modelService;
this._keepIdleModels = keepIdleModels;
@ -518,7 +525,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
if (!model) {
return Promise.resolve(null);
}
let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId());
const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();
let wordDef = wordDefRegExp.source;
let wordDefFlags = regExpFlags(wordDefRegExp);
return proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags);
@ -531,7 +538,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
if (!model) {
return null;
}
let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId());
const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();
let wordDef = wordDefRegExp.source;
let wordDefFlags = regExpFlags(wordDefRegExp);
return proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags);

View file

@ -69,7 +69,7 @@ function detectModeId(modelService: IModelService, languageService: ILanguageSer
return null; // we need a resource at least
}
let modeId: string | null = null;
let languageId: string | null = null;
// Data URI: check for encoded metadata
if (resource.scheme === Schemas.data) {
@ -77,7 +77,7 @@ function detectModeId(modelService: IModelService, languageService: ILanguageSer
const mime = metadata.get(DataUri.META_DATA_MIME);
if (mime) {
modeId = languageService.getModeId(mime);
languageId = languageService.getLanguageIdForMimeType(mime);
}
}
@ -85,17 +85,17 @@ function detectModeId(modelService: IModelService, languageService: ILanguageSer
else {
const model = modelService.getModel(resource);
if (model) {
modeId = model.getLanguageId();
languageId = model.getLanguageId();
}
}
// only take if the mode is specific (aka no just plain text)
if (modeId && modeId !== PLAINTEXT_MODE_ID) {
return modeId;
if (languageId && languageId !== PLAINTEXT_MODE_ID) {
return languageId;
}
// otherwise fallback to path based detection
return languageService.getModeIdByFilepathOrFirstLine(resource);
return languageService.getLanguageIdByFilepathOrFirstLine(resource);
}
export function cssEscape(str: string): string {

View file

@ -36,22 +36,30 @@ export interface ILanguageService {
// --- reading
isRegisteredLanguageId(languageId: string): boolean;
isRegisteredMimeType(mimeType: string): boolean;
getRegisteredLanguageIds(): string[];
getRegisteredLanguageNames(): string[];
getExtensions(alias: string): string[];
getFilenames(alias: string): string[];
getExtensions(alias: string): string[]; // TODO
getFilenames(alias: string): string[]; // TODO
getMimeTypeForLanguageId(languageId: string): string | null;
getLanguageName(languageId: string): string | null;
getLanguageIdForLanguageName(languageName: string): string | null;
getModeIdByFilepathOrFirstLine(resource: URI, firstLine?: string): string | null;
getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string): string | null;
getLanguageIdForLanguageName(languageName: string): string | null; // TODO
getLanguageIdForMimeType(mimeType: string | null | undefined): string | null;
getLanguageIdByFilepathOrFirstLine(resource: URI, firstLine?: string): string | null;
validateLanguageId(languageId: string): string | null;
getConfigurationFiles(languageId: string): URI[];
// --- instantiation
create(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): ILanguageSelection;
createByLanguageName(languageName: string): ILanguageSelection;
/**
* Will fall back to 'plaintext' if `languageId` is unknown.
*/
createById(languageId: string | null | undefined): ILanguageSelection;
/**
* Will fall back to 'plaintext' if `mimeType` is unknown.
*/
createByMimeType(mimeType: string | null | undefined): ILanguageSelection;
/**
* Will fall back to 'plaintext' if the `languageId` cannot be determined.
*/
createByFilepathOrFirstLine(resource: URI | null, firstLine?: string): ILanguageSelection;
triggerMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): void;

View file

@ -11,6 +11,7 @@ import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry';
import { ILanguageSelection, ILanguageService } from 'vs/editor/common/services/languageService';
import { firstOrDefault } from 'vs/base/common/arrays';
import { ILanguageIdCodec } from 'vs/editor/common/modes';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
class LanguageSelection implements ILanguageSelection {
@ -76,14 +77,10 @@ export class LanguageService extends Disposable implements ILanguageService {
super.dispose();
}
public isRegisteredLanguageId(languageId: string): boolean {
public isRegisteredLanguageId(languageId: string | null | undefined): boolean {
return this._registry.isRegisteredLanguageId(languageId);
}
public isRegisteredMimeType(mimeType: string): boolean {
return this._registry.isRegisteredMimeType(mimeType);
}
public getRegisteredLanguageIds(): string[] {
return this._registry.getRegisteredLanguageIds();
}
@ -112,12 +109,16 @@ export class LanguageService extends Disposable implements ILanguageService {
return this._registry.getLanguageIdForLanguageName(alias);
}
public getModeIdByFilepathOrFirstLine(resource: URI | null, firstLine?: string): string | null {
const modeIds = this._registry.getModeIdsFromFilepathOrFirstLine(resource, firstLine);
public getLanguageIdForMimeType(mimeType: string | null | undefined): string | null {
return this._registry.getLanguageIdForMimeType(mimeType);
}
public getLanguageIdByFilepathOrFirstLine(resource: URI | null, firstLine?: string): string | null {
const modeIds = this._registry.getLanguageIdByFilepathOrFirstLine(resource, firstLine);
return firstOrDefault(modeIds, null);
}
public getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): string | null {
private getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): string | null {
const modeIds = this._registry.extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds);
return firstOrDefault(modeIds, null);
}
@ -132,28 +133,29 @@ export class LanguageService extends Disposable implements ILanguageService {
// --- instantiation
public create(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): ILanguageSelection {
public createById(languageId: string | null | undefined): ILanguageSelection {
return new LanguageSelection(this.onLanguagesMaybeChanged, () => {
const languageId = this.getModeId(commaSeparatedMimetypesOrCommaSeparatedIds);
return this._createModeAndGetLanguageIdentifier(languageId);
const validLanguageId = (languageId && this.isRegisteredLanguageId(languageId) ? languageId : PLAINTEXT_MODE_ID);
this._getOrCreateMode(validLanguageId);
return validLanguageId;
});
}
public createByLanguageName(languageName: string): ILanguageSelection {
public createByMimeType(mimeType: string | null | undefined): ILanguageSelection {
return new LanguageSelection(this.onLanguagesMaybeChanged, () => {
const languageId = this._getModeIdByLanguageName(languageName);
const languageId = this.getLanguageIdForMimeType(mimeType);
return this._createModeAndGetLanguageIdentifier(languageId);
});
}
public createByFilepathOrFirstLine(resource: URI | null, firstLine?: string): ILanguageSelection {
return new LanguageSelection(this.onLanguagesMaybeChanged, () => {
const languageId = this.getModeIdByFilepathOrFirstLine(resource, firstLine);
const languageId = this.getLanguageIdByFilepathOrFirstLine(resource, firstLine);
return this._createModeAndGetLanguageIdentifier(languageId);
});
}
private _createModeAndGetLanguageIdentifier(languageId: string | null): string {
private _createModeAndGetLanguageIdentifier(languageId: string | null | undefined): string {
// Fall back to plain text if no mode was found
const validLanguageId = this.validateLanguageId(languageId || 'plaintext') || NULL_MODE_ID;
this._getOrCreateMode(validLanguageId);
@ -166,10 +168,6 @@ export class LanguageService extends Disposable implements ILanguageService {
this._getOrCreateMode(languageId || 'plaintext');
}
private _getModeIdByLanguageName(languageName: string): string | null {
return this._registry.getModeIdFromLanguageName(languageName);
}
private _getOrCreateMode(languageId: string): void {
if (!this._encounteredLanguages.has(languageId)) {
this._encounteredLanguages.add(languageId);

View file

@ -257,14 +257,13 @@ export class LanguagesRegistry extends Disposable {
}
}
public isRegisteredLanguageId(languageId: string): boolean {
public isRegisteredLanguageId(languageId: string | null | undefined): boolean {
if (!languageId) {
return false;
}
return hasOwnProperty.call(this._languages, languageId);
}
public isRegisteredMimeType(mimeType: string): boolean {
return hasOwnProperty.call(this._mimeTypesMap, mimeType);
}
public getRegisteredLanguageIds(): string[] {
return Object.keys(this._languages);
}
@ -287,6 +286,16 @@ export class LanguagesRegistry extends Disposable {
return this._lowercaseNameMap[languageNameLower];
}
public getLanguageIdForMimeType(mimeType: string | null | undefined): string | null {
if (!mimeType) {
return null;
}
if (hasOwnProperty.call(this._mimeTypesMap, mimeType)) {
return this._mimeTypesMap[mimeType];
}
return null;
}
public getConfigurationFiles(languageId: string): URI[] {
if (!hasOwnProperty.call(this._languages, languageId)) {
return [];
@ -323,7 +332,7 @@ export class LanguagesRegistry extends Disposable {
);
}
public validateLanguageId(languageId: string | null): string | null {
public validateLanguageId(languageId: string | null | undefined): string | null {
if (!languageId || languageId === NULL_MODE_ID) {
return NULL_MODE_ID;
}
@ -345,7 +354,7 @@ export class LanguagesRegistry extends Disposable {
return null;
}
public getModeIdsFromFilepathOrFirstLine(resource: URI | null, firstLine?: string): string[] {
public getLanguageIdByFilepathOrFirstLine(resource: URI | null, firstLine?: string): string[] {
if (!resource && !firstLine) {
return [];
}

View file

@ -111,7 +111,7 @@ export class TextResourceConfigurationService extends Disposable implements ITex
if (model) {
return position ? model.getLanguageIdAtPosition(position.lineNumber, position.column) : model.getLanguageId();
}
return this.languageService.getModeIdByFilepathOrFirstLine(resource);
return this.languageService.getLanguageIdByFilepathOrFirstLine(resource);
}
private toResourceConfigurationChangeEvent(configurationChangeEvent: IConfigurationChangeEvent): ITextResourceConfigurationChangeEvent {

View file

@ -7,13 +7,14 @@ import { URI } from 'vs/base/common/uri';
import { EditorWorkerClient } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
import * as types from 'vs/base/common/types';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
/**
* Create a new web worker that has model syncing capabilities built in.
* Specify an AMD module to load that will `create` an object that will be proxied.
*/
export function createWebWorker<T>(modelService: IModelService, opts: IWebWorkerOptions): MonacoWebWorker<T> {
return new MonacoWebWorkerImpl<T>(modelService, opts);
export function createWebWorker<T>(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions): MonacoWebWorker<T> {
return new MonacoWebWorkerImpl<T>(modelService, languageConfigurationService, opts);
}
/**
@ -67,8 +68,8 @@ class MonacoWebWorkerImpl<T> extends EditorWorkerClient implements MonacoWebWork
private _foreignModuleCreateData: any | null;
private _foreignProxy: Promise<T> | null;
constructor(modelService: IModelService, opts: IWebWorkerOptions) {
super(modelService, opts.keepIdleModels || false, opts.label);
constructor(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions) {
super(modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService);
this._foreignModuleId = opts.moduleId;
this._foreignModuleCreateData = opts.createData || null;
this._foreignModuleHost = opts.host || null;

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IViewLineTokens, LineTokens } from 'vs/editor/common/core/lineTokens';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Position } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { EndOfLinePreference, ITextModel, PositionAffinity } from 'vs/editor/common/model';
@ -19,14 +19,14 @@ export interface IModelLineProjection {
*/
setVisible(isVisible: boolean): IModelLineProjection;
getLineBreakData(): ModelLineProjectionData | null;
getProjectionData(): ModelLineProjectionData | null;
getViewLineCount(): number;
getViewLineContent(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): string;
getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;
getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;
getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;
getViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData;
getViewLinesData(model: ISimpleModel, modelLineNumber: number, fromOutputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void;
getViewLinesData(model: ISimpleModel, modelLineNumber: number, outputLineIdx: number, lineCount: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void;
getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number;
getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number, affinity?: PositionAffinity): Position;
@ -63,11 +63,11 @@ export function createModelLineProjection(lineBreakData: ModelLineProjectionData
* * inject text
*/
class ModelLineProjection implements IModelLineProjection {
private readonly _lineBreakData: ModelLineProjectionData;
private readonly _projectionData: ModelLineProjectionData;
private _isVisible: boolean;
constructor(lineBreakData: ModelLineProjectionData, isVisible: boolean) {
this._lineBreakData = lineBreakData;
this._projectionData = lineBreakData;
this._isVisible = isVisible;
}
@ -80,133 +80,166 @@ class ModelLineProjection implements IModelLineProjection {
return this;
}
public getLineBreakData(): ModelLineProjectionData | null {
return this._lineBreakData;
public getProjectionData(): ModelLineProjectionData | null {
return this._projectionData;
}
public getViewLineCount(): number {
if (!this._isVisible) {
return 0;
}
return this._lineBreakData.getOutputLineCount();
}
private getInputStartOffsetOfOutputLineIndex(outputLineIndex: number): number {
return this._lineBreakData.translateToInputOffset(outputLineIndex, 0);
}
private getInputEndOffsetOfOutputLineIndex(outputLineIndex: number): number {
return this._lineBreakData.translateToInputOffset(outputLineIndex, this._lineBreakData.getMaxOutputOffset(outputLineIndex));
return this._projectionData.getOutputLineCount();
}
public getViewLineContent(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): string {
this.assertVisible();
this._assertVisible();
// These offsets refer to model text with injected text.
const startOffset = outputLineIndex > 0 ? this._lineBreakData.breakOffsets[outputLineIndex - 1] : 0;
const endOffset = outputLineIndex < this._lineBreakData.breakOffsets.length
? this._lineBreakData.breakOffsets[outputLineIndex]
// This case might not be possible anyway, but we clamp the value to be on the safe side.
: this._lineBreakData.breakOffsets[this._lineBreakData.breakOffsets.length - 1];
const startOffsetInInputWithInjections = outputLineIndex > 0 ? this._projectionData.breakOffsets[outputLineIndex - 1] : 0;
const endOffsetInInputWithInjections = this._projectionData.breakOffsets[outputLineIndex];
let r: string;
if (this._lineBreakData.injectionOffsets !== null) {
const injectedTexts = this._lineBreakData.injectionOffsets.map((offset, idx) => new LineInjectedText(0, 0, offset + 1, this._lineBreakData.injectionOptions![idx], 0));
r = LineInjectedText.applyInjectedText(model.getLineContent(modelLineNumber), injectedTexts).substring(startOffset, endOffset);
if (this._projectionData.injectionOffsets !== null) {
const injectedTexts = this._projectionData.injectionOffsets.map(
(offset, idx) => new LineInjectedText(
0,
0,
offset + 1,
this._projectionData.injectionOptions![idx],
0
)
);
const lineWithInjections = LineInjectedText.applyInjectedText(
model.getLineContent(modelLineNumber),
injectedTexts
);
r = lineWithInjections.substring(startOffsetInInputWithInjections, endOffsetInInputWithInjections);
} else {
r = model.getValueInRange({
startLineNumber: modelLineNumber,
startColumn: startOffset + 1,
startColumn: startOffsetInInputWithInjections + 1,
endLineNumber: modelLineNumber,
endColumn: endOffset + 1
endColumn: endOffsetInInputWithInjections + 1
});
}
if (outputLineIndex > 0) {
r = spaces(this._lineBreakData.wrappedTextIndentLength) + r;
r = spaces(this._projectionData.wrappedTextIndentLength) + r;
}
return r;
}
public getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number {
this.assertVisible();
return this._lineBreakData.getLineLength(outputLineIndex);
this._assertVisible();
return this._projectionData.getLineLength(outputLineIndex);
}
public getViewLineMinColumn(_model: ITextModel, _modelLineNumber: number, outputLineIndex: number): number {
this.assertVisible();
return this._lineBreakData.getMinOutputOffset(outputLineIndex) + 1;
this._assertVisible();
return this._projectionData.getMinOutputOffset(outputLineIndex) + 1;
}
public getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number {
this.assertVisible();
return this._lineBreakData.getMaxOutputOffset(outputLineIndex) + 1;
this._assertVisible();
return this._projectionData.getMaxOutputOffset(outputLineIndex) + 1;
}
/**
* Try using {@link getViewLinesData} instead.
*/
public getViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData {
this.assertVisible();
const lineBreakData = this._lineBreakData;
const deltaStartIndex = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);
const arr = new Array<ViewLineData>();
this.getViewLinesData(model, modelLineNumber, outputLineIndex, 1, 0, [true], arr);
return arr[0];
}
public getViewLinesData(model: ISimpleModel, modelLineNumber: number, outputLineIdx: number, lineCount: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void {
this._assertVisible();
const lineBreakData = this._projectionData;
const injectionOffsets = lineBreakData.injectionOffsets;
const injectionOptions = lineBreakData.injectionOptions;
let tokens: IViewLineTokens;
let inlineDecorations: null | SingleLineInlineDecoration[];
let inlineDecorationsPerOutputLine: SingleLineInlineDecoration[][] | null = null;
if (injectionOffsets) {
const lineTokens = model.getLineTokens(modelLineNumber).withInserted(injectionOffsets.map((offset, idx) => ({
inlineDecorationsPerOutputLine = [];
let totalInjectedTextLengthBefore = 0;
let currentInjectedOffset = 0;
for (let outputLineIndex = 0; outputLineIndex < lineBreakData.getOutputLineCount(); outputLineIndex++) {
const inlineDecorations = new Array<SingleLineInlineDecoration>();
inlineDecorationsPerOutputLine[outputLineIndex] = inlineDecorations;
const lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;
const lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];
while (currentInjectedOffset < injectionOffsets.length) {
const length = injectionOptions![currentInjectedOffset].content.length;
const injectedTextStartOffsetInInputWithInjections = injectionOffsets[currentInjectedOffset] + totalInjectedTextLengthBefore;
const injectedTextEndOffsetInInputWithInjections = injectedTextStartOffsetInInputWithInjections + length;
if (injectedTextStartOffsetInInputWithInjections > lineEndOffsetInInputWithInjections) {
// Injected text only starts in later wrapped lines.
break;
}
if (lineStartOffsetInInputWithInjections < injectedTextEndOffsetInInputWithInjections) {
// Injected text ends after or in this line (but also starts in or before this line).
const options = injectionOptions![currentInjectedOffset];
if (options.inlineClassName) {
const offset = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);
const start = offset + Math.max(injectedTextStartOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, 0);
const end = offset + Math.min(injectedTextEndOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections);
if (start !== end) {
inlineDecorations.push(new SingleLineInlineDecoration(start, end, options.inlineClassName, options.inlineClassNameAffectsLetterSpacing!));
}
}
}
totalInjectedTextLengthBefore += length;
currentInjectedOffset++;
}
}
}
let lineWithInjections: LineTokens;
if (injectionOffsets) {
lineWithInjections = model.getLineTokens(modelLineNumber).withInserted(injectionOffsets.map((offset, idx) => ({
offset,
text: injectionOptions![idx].content,
tokenMetadata: LineTokens.defaultTokenMetadata
})));
const lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;
const lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];
tokens = lineTokens.sliceAndInflate(lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections, deltaStartIndex);
inlineDecorations = new Array<SingleLineInlineDecoration>();
let totalInjectedTextLengthBefore = 0;
for (let i = 0; i < injectionOffsets.length; i++) {
const length = injectionOptions![i].content.length;
const injectedTextStartOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore;
const injectedTextEndOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore + length;
if (injectedTextStartOffsetInInputWithInjections > lineEndOffsetInInputWithInjections) {
// Injected text only starts in later wrapped lines.
break;
}
if (lineStartOffsetInInputWithInjections < injectedTextEndOffsetInInputWithInjections) {
// Injected text ends after or in this line (but also starts in or before this line).
const options = injectionOptions![i];
if (options.inlineClassName) {
const offset = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);
const start = offset + Math.max(injectedTextStartOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, 0);
const end = offset + Math.min(injectedTextEndOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections);
if (start !== end) {
inlineDecorations.push(new SingleLineInlineDecoration(start, end, options.inlineClassName, options.inlineClassNameAffectsLetterSpacing!));
}
}
}
totalInjectedTextLengthBefore += length;
}
} else {
const startOffset = this.getInputStartOffsetOfOutputLineIndex(outputLineIndex);
const endOffset = this.getInputEndOffsetOfOutputLineIndex(outputLineIndex);
const lineTokens = model.getLineTokens(modelLineNumber);
tokens = lineTokens.sliceAndInflate(startOffset, endOffset, deltaStartIndex);
inlineDecorations = null;
lineWithInjections = model.getLineTokens(modelLineNumber);
}
for (let outputLineIndex = outputLineIdx; outputLineIndex < outputLineIdx + lineCount; outputLineIndex++) {
let globalIndex = globalStartIndex + outputLineIndex - outputLineIdx;
if (!needed[globalIndex]) {
result[globalIndex] = null;
continue;
}
result[globalIndex] = this._getViewLineData(lineWithInjections, inlineDecorationsPerOutputLine ? inlineDecorationsPerOutputLine[outputLineIndex] : null, outputLineIndex);
}
}
private _getViewLineData(lineWithInjections: LineTokens, inlineDecorations: null | SingleLineInlineDecoration[], outputLineIndex: number): ViewLineData {
this._assertVisible();
const lineBreakData = this._projectionData;
const deltaStartIndex = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);
const lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;
const lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];
const tokens = lineWithInjections.sliceAndInflate(lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections, deltaStartIndex);
let lineContent = tokens.getLineContent();
if (outputLineIndex > 0) {
lineContent = spaces(lineBreakData.wrappedTextIndentLength) + lineContent;
}
const minColumn = this._lineBreakData.getMinOutputOffset(outputLineIndex) + 1;
const minColumn = this._projectionData.getMinOutputOffset(outputLineIndex) + 1;
const maxColumn = lineContent.length + 1;
const continuesWithWrappedLine = (outputLineIndex + 1 < this.getViewLineCount());
const startVisibleColumn = (outputLineIndex === 0 ? 0 : lineBreakData.breakOffsetsVisibleColumn[outputLineIndex - 1]);
@ -222,47 +255,35 @@ class ModelLineProjection implements IModelLineProjection {
);
}
public getViewLinesData(model: ITextModel, modelLineNumber: number, fromOutputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void {
this.assertVisible();
for (let outputLineIndex = fromOutputLineIndex; outputLineIndex < toOutputLineIndex; outputLineIndex++) {
let globalIndex = globalStartIndex + outputLineIndex - fromOutputLineIndex;
if (!needed[globalIndex]) {
result[globalIndex] = null;
continue;
}
result[globalIndex] = this.getViewLineData(model, modelLineNumber, outputLineIndex);
}
}
public getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number {
this.assertVisible();
return this._lineBreakData.translateToInputOffset(outputLineIndex, outputColumn - 1) + 1;
this._assertVisible();
return this._projectionData.translateToInputOffset(outputLineIndex, outputColumn - 1) + 1;
}
public getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number, affinity: PositionAffinity = PositionAffinity.None): Position {
this.assertVisible();
let r = this._lineBreakData.translateToOutputPosition(inputColumn - 1, affinity);
this._assertVisible();
let r = this._projectionData.translateToOutputPosition(inputColumn - 1, affinity);
return r.toPosition(deltaLineNumber);
}
public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number {
this.assertVisible();
const r = this._lineBreakData.translateToOutputPosition(inputColumn - 1);
this._assertVisible();
const r = this._projectionData.translateToOutputPosition(inputColumn - 1);
return deltaLineNumber + r.outputLineIndex;
}
public normalizePosition(outputLineIndex: number, outputPosition: Position, affinity: PositionAffinity): Position {
const baseViewLineNumber = outputPosition.lineNumber - outputLineIndex;
const normalizedOutputPosition = this._lineBreakData.normalizeOutputPosition(outputLineIndex, outputPosition.column - 1, affinity);
const normalizedOutputPosition = this._projectionData.normalizeOutputPosition(outputLineIndex, outputPosition.column - 1, affinity);
const result = normalizedOutputPosition.toPosition(baseViewLineNumber);
return result;
}
public getInjectedTextAt(outputLineIndex: number, outputColumn: number): InjectedText | null {
return this._lineBreakData.getInjectedText(outputLineIndex, outputColumn - 1);
return this._projectionData.getInjectedText(outputLineIndex, outputColumn - 1);
}
private assertVisible() {
private _assertVisible() {
if (!this._isVisible) {
throw new Error('Not supported');
}
@ -288,7 +309,7 @@ class IdentityModelLineProjection implements IModelLineProjection {
return HiddenModelLineProjection.INSTANCE;
}
public getLineBreakData(): ModelLineProjectionData | null {
public getProjectionData(): ModelLineProjectionData | null {
return null;
}
@ -374,7 +395,7 @@ class HiddenModelLineProjection implements IModelLineProjection {
return IdentityModelLineProjection.INSTANCE;
}
public getLineBreakData(): ModelLineProjectionData | null {
public getProjectionData(): ModelLineProjectionData | null {
return null;
}

View file

@ -23,6 +23,7 @@ import { IActiveIndentGuideInfo, BracketGuideOptions, IndentGuide } from 'vs/edi
import { ModelDecorationMinimapOptions, ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModel';
import * as textModelEvents from 'vs/editor/common/model/textModelEvents';
import { ColorId, TokenizationRegistry } from 'vs/editor/common/modes';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer';
import { EditorTheme } from 'vs/editor/common/view/viewContext';
@ -65,7 +66,8 @@ export class ViewModel extends Disposable implements IViewModel {
model: ITextModel,
domLineBreaksComputerFactory: ILineBreaksComputerFactory,
monospaceLineBreaksComputerFactory: ILineBreaksComputerFactory,
scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable
scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable,
private readonly languageConfigurationService: ILanguageConfigurationService
) {
super();
@ -74,7 +76,7 @@ export class ViewModel extends Disposable implements IViewModel {
this.model = model;
this._eventDispatcher = new ViewModelEventDispatcher();
this.onEvent = this._eventDispatcher.onEvent;
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration);
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);
this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50));
this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0));
this._hasFocus = false;
@ -256,7 +258,7 @@ export class ViewModel extends Disposable implements IViewModel {
}
if (CursorConfiguration.shouldRecreate(e)) {
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration);
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);
this._cursor.updateConfiguration(this.cursorConfig);
}
}
@ -413,12 +415,12 @@ export class ViewModel extends Disposable implements IViewModel {
this._register(this.model.onDidChangeLanguageConfiguration((e) => {
this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewLanguageConfigurationEvent());
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration);
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);
this._cursor.updateConfiguration(this.cursorConfig);
}));
this._register(this.model.onDidChangeLanguage((e) => {
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration);
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);
this._cursor.updateConfiguration(this.cursorConfig);
}));
@ -439,7 +441,7 @@ export class ViewModel extends Disposable implements IViewModel {
this._updateConfigurationViewLineCount.schedule();
}
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration);
this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);
this._cursor.updateConfiguration(this.cursorConfig);
}));

View file

@ -289,7 +289,7 @@ export class ViewModelLinesFromProjectedModel implements IViewModelLines {
if (onlyWrappingColumnChanged) {
previousLineBreaks = [];
for (let i = 0, len = this.modelLineProjections.length; i < len; i++) {
previousLineBreaks[i] = this.modelLineProjections[i].getLineBreakData();
previousLineBreaks[i] = this.modelLineProjections[i].getProjectionData();
}
}
@ -709,9 +709,8 @@ export class ViewModelLinesFromProjectedModel implements IViewModelLines {
lastLine = true;
remainingViewLineCount = viewEndLineNumber - viewLineNumber + 1;
}
let toViewLineIndex = fromViewLineIndex + remainingViewLineCount;
line.getViewLinesData(this.model, modelLineIndex + 1, fromViewLineIndex, toViewLineIndex, viewLineNumber - viewStartLineNumber, needed, result);
line.getViewLinesData(this.model, modelLineIndex + 1, fromViewLineIndex, remainingViewLineCount, viewLineNumber - viewStartLineNumber, needed, result);
viewLineNumber += remainingViewLineCount;
@ -1160,10 +1159,7 @@ export class ViewModelLinesFromModelAsIs implements IViewModelLines {
let result: Array<ViewLineData | null> = [];
for (let lineNumber = viewStartLineNumber; lineNumber <= viewEndLineNumber; lineNumber++) {
let idx = lineNumber - viewStartLineNumber;
if (!needed[idx]) {
result[idx] = null;
}
result[idx] = this.getViewLineData(lineNumber);
result[idx] = needed[idx] ? this.getViewLineData(lineNumber) : null;
}
return result;

View file

@ -204,7 +204,7 @@ export class GotoDefinitionAtPositionEditorContribution implements IEditorContri
wordRange = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
}
const languageId = this.languageService.getModeIdByFilepathOrFirstLine(textEditorModel.uri);
const languageId = this.languageService.getLanguageIdByFilepathOrFirstLine(textEditorModel.uri);
this.addDecoration(
wordRange,
new MarkdownString().appendCodeblock(languageId ? languageId : '', previewValue)

View file

@ -235,7 +235,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
const symbol = symbols[index];
const symbolLabel = trim(symbol.name);
const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`;
const symbolLabelWithIcon = `$(${SymbolKinds.toIcon(symbol.kind).id}) ${symbolLabel}`;
const symbolLabelIconOffset = symbolLabelWithIcon.length - symbolLabel.length;
let containerLabel = symbol.containerName;

View file

@ -9,7 +9,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import { LRUCache, TernarySearchTree } from 'vs/base/common/map';
import { IPosition } from 'vs/editor/common/core/position';
import { ITextModel } from 'vs/editor/common/model';
import { CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
import { CompletionItemKind, CompletionItemKinds } from 'vs/editor/common/modes';
import { CompletionItem } from 'vs/editor/contrib/suggest/suggest';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@ -138,7 +138,7 @@ export class LRUMemory extends Memory {
let seq = 0;
for (const [key, value] of data) {
value.touch = seq;
value.type = typeof value.type === 'number' ? value.type : completionKindFromString(value.type);
value.type = typeof value.type === 'number' ? value.type : CompletionItemKinds.fromString(value.type);
this._cache.set(key, value);
}
this._seq = this._cache.size;
@ -206,7 +206,7 @@ export class PrefixMemory extends Memory {
if (data.length > 0) {
this._seq = data[0][1].touch + 1;
for (const [key, value] of data) {
value.type = typeof value.type === 'number' ? value.type : completionKindFromString(value.type);
value.type = typeof value.type === 'number' ? value.type : CompletionItemKinds.fromString(value.type);
this._trie.set(key, value);
}
}

View file

@ -8,14 +8,14 @@ import { $, append, hide, show } from 'vs/base/browser/dom';
import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { IListRenderer } from 'vs/base/browser/ui/list/list';
import { flatten } from 'vs/base/common/arrays';
import { Codicon } from 'vs/base/common/codicons';
import { Codicon, CSSIcon } from 'vs/base/common/codicons';
import { Emitter, Event } from 'vs/base/common/event';
import { createMatches } from 'vs/base/common/filters';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorOption, EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { CompletionItemKind, CompletionItemTag, completionKindToCssClass } from 'vs/editor/common/modes';
import { CompletionItemKind, CompletionItemKinds, CompletionItemTag } from 'vs/editor/common/modes';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ILanguageService } from 'vs/editor/common/services/languageService';
@ -198,7 +198,7 @@ export class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTe
// normal icon
data.icon.className = 'icon hide';
data.iconContainer.className = '';
data.iconContainer.classList.add('suggest-icon', ...completionKindToCssClass(completion.kind).split(' '));
data.iconContainer.classList.add('suggest-icon', ...CSSIcon.asClassNameArray(CompletionItemKinds.toIcon(completion.kind)));
}
if (completion.tags && completion.tags.indexOf(CompletionItemTag.Deprecated) >= 0) {

View file

@ -22,6 +22,7 @@ import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance';
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
import { NullLogService } from 'vs/platform/log/common/log';
suite('suggest, word distance', function () {
@ -65,7 +66,7 @@ suite('suggest, word distance', function () {
private _worker = new EditorSimpleWorker(new class extends mock<EditorWorkerHost>() { }, null);
constructor() {
super(modelService, new class extends mock<ITextResourceConfigurationService>() { }, new NullLogService());
super(modelService, new class extends mock<ITextResourceConfigurationService>() { }, new NullLogService(), new TestLanguageConfigurationService());
this._worker.acceptNewModel({
url: model.uri.toString(),
lines: model.getLinesContent(),

View file

@ -31,11 +31,12 @@ export class Colorizer {
public static colorizeElement(themeService: IStandaloneThemeService, languageService: ILanguageService, domNode: HTMLElement, options: IColorizerElementOptions): Promise<void> {
options = options || {};
let theme = options.theme || 'vs';
let mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang');
const mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang');
if (!mimeType) {
console.error('Mode not detected');
return Promise.resolve();
}
const languageId = languageService.getLanguageIdForMimeType(mimeType) || mimeType;
themeService.setTheme(theme);
@ -45,10 +46,10 @@ export class Colorizer {
const trustedhtml = ttPolicy?.createHTML(str) ?? str;
domNode.innerHTML = trustedhtml as string;
};
return this.colorize(languageService, text || '', mimeType, options).then(render, (err) => console.error(err));
return this.colorize(languageService, text || '', languageId, options).then(render, (err) => console.error(err));
}
public static colorize(languageService: ILanguageService, text: string, mimeType: string, options: IColorizerOptions | null | undefined): Promise<string> {
public static colorize(languageService: ILanguageService, text: string, languageId: string, options: IColorizerOptions | null | undefined): Promise<string> {
const languageIdCodec = languageService.languageIdCodec;
let tabSize = 4;
if (options && typeof options.tabSize === 'number') {
@ -59,20 +60,19 @@ export class Colorizer {
text = text.substr(1);
}
let lines = strings.splitLines(text);
let language = languageService.getModeId(mimeType);
if (!language) {
if (!languageService.isRegisteredLanguageId(languageId)) {
return Promise.resolve(_fakeColorize(lines, tabSize, languageIdCodec));
}
// Send out the event to create the mode
languageService.triggerMode(language);
languageService.triggerMode(languageId);
const tokenizationSupport = TokenizationRegistry.get(language);
const tokenizationSupport = TokenizationRegistry.get(languageId);
if (tokenizationSupport) {
return _colorize(lines, tabSize, tokenizationSupport, languageIdCodec);
}
const tokenizationSupportPromise = TokenizationRegistry.getPromise(language);
const tokenizationSupportPromise = TokenizationRegistry.getPromise(languageId);
if (tokenizationSupportPromise) {
// A tokenizer will be registered soon
return new Promise<string>((resolve, reject) => {
@ -95,7 +95,7 @@ export class Colorizer {
timeout.dispose();
timeout = null;
}
const tokenizationSupport = TokenizationRegistry.get(language!);
const tokenizationSupport = TokenizationRegistry.get(languageId!);
if (tokenizationSupport) {
_colorize(lines, tabSize, tokenizationSupport, languageIdCodec).then(resolve, reject);
return;
@ -107,7 +107,7 @@ export class Colorizer {
timeout = new TimeoutTimer();
timeout.cancelAndSet(execute, 500);
listener = TokenizationRegistry.onDidChange((e) => {
if (e.changedLanguages.indexOf(language!) >= 0) {
if (e.changedLanguages.indexOf(languageId!) >= 0) {
execute();
}
});

View file

@ -35,7 +35,8 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ILanguageSelection, ILanguageService } from 'vs/editor/common/services/languageService';
import { URI } from 'vs/base/common/uri';
import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl';
import { Mimes } from 'vs/base/common/mime';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
/**
* Description of an action contribution
@ -270,12 +271,13 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
@IKeybindingService keybindingService: IKeybindingService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService,
@IAccessibilityService accessibilityService: IAccessibilityService
@IAccessibilityService accessibilityService: IAccessibilityService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
) {
const options = { ..._options };
options.ariaLabel = options.ariaLabel || StandaloneCodeEditorNLS.editorViewAccessibleLabel;
options.ariaLabel = options.ariaLabel + ';' + (StandaloneCodeEditorNLS.accessibilityHelpMessage);
super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService);
super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService);
if (keybindingService instanceof StandaloneKeybindingService) {
this._standaloneKeybindingService = keybindingService;
@ -415,6 +417,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
@IAccessibilityService accessibilityService: IAccessibilityService,
@IModelService modelService: IModelService,
@ILanguageService languageService: ILanguageService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
) {
const options = { ..._options };
updateConfigurationService(configurationService, options, false);
@ -427,7 +430,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
}
let _model: ITextModel | null | undefined = options.model;
delete options.model;
super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService);
super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService, languageConfigurationService);
this._contextViewService = <ContextViewService>contextViewService;
this._configurationService = configurationService;
@ -437,7 +440,8 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
let model: ITextModel | null;
if (typeof _model === 'undefined') {
model = createTextModel(modelService, languageService, options.value || '', options.language || Mimes.text, undefined);
const languageId = languageService.getLanguageIdForMimeType(options.language) || options.language || PLAINTEXT_MODE_ID;
model = createTextModel(modelService, languageService, options.value || '', languageId, undefined);
this._ownsModel = true;
} else {
model = _model;
@ -573,9 +577,9 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
/**
* @internal
*/
export function createTextModel(modelService: IModelService, languageService: ILanguageService, value: string, language: string | undefined, uri: URI | undefined): ITextModel {
export function createTextModel(modelService: IModelService, languageService: ILanguageService, value: string, languageId: string | undefined, uri: URI | undefined): ITextModel {
value = value || '';
if (!language) {
if (!languageId) {
const firstLF = value.indexOf('\n');
let firstLine = value;
if (firstLF !== -1) {
@ -583,7 +587,7 @@ export function createTextModel(modelService: IModelService, languageService: IL
}
return doCreateModel(modelService, value, languageService.createByFilepathOrFirstLine(uri || null, firstLine), uri);
}
return doCreateModel(modelService, value, languageService.create(language), uri);
return doCreateModel(modelService, value, languageService.createById(languageId), uri);
}
/**

View file

@ -43,6 +43,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl';
import { splitLines } from 'vs/base/common/strings';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
@ -91,6 +92,7 @@ export function create(domElement: HTMLElement, options?: IStandaloneEditorConst
services.get(IAccessibilityService),
services.get(IModelService),
services.get(ILanguageService),
services.get(ILanguageConfigurationService),
);
});
}
@ -148,11 +150,13 @@ export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: ID
* You can specify the language that should be set for this model or let the language be inferred from the `uri`.
*/
export function createModel(value: string, language?: string, uri?: URI): ITextModel {
const languageService = StaticServices.languageService.get();
const languageId = languageService.getLanguageIdForMimeType(language) || language;
return createTextModel(
StaticServices.modelService.get(),
StaticServices.languageService.get(),
languageService,
value,
language,
languageId,
uri
);
}
@ -161,7 +165,7 @@ export function createModel(value: string, language?: string, uri?: URI): ITextM
* Change the language for a model.
*/
export function setModelLanguage(model: ITextModel, languageId: string): void {
StaticServices.modelService.get().setMode(model, StaticServices.languageService.get().create(languageId));
StaticServices.modelService.get().setMode(model, StaticServices.languageService.get().createById(languageId));
}
/**
@ -238,7 +242,7 @@ export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextMo
* Specify an AMD module to load that will `create` an object that will be proxied.
*/
export function createWebWorker<T>(opts: IWebWorkerOptions): MonacoWebWorker<T> {
return actualCreateWebWorker<T>(StaticServices.modelService.get(), opts);
return actualCreateWebWorker<T>(StaticServices.modelService.get(), StaticServices.languageConfigurationService.get(), opts);
}
/**

View file

@ -184,7 +184,7 @@ export module StaticServices {
export const storageService = define(IStorageService, () => new InMemoryStorageService());
export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o)));
export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o), languageConfigurationService.get(o)));
}
export class DynamicStandaloneServices extends Disposable {

View file

@ -744,13 +744,14 @@ export class MonarchTokenizer implements modes.ITokenizationSupport {
}
const computeNewStateForEmbeddedMode = (enteringEmbeddedMode: string) => {
// substitute language alias to known modes to support syntax highlighting
let enteringEmbeddedLanguageId = this._languageService.getLanguageIdForLanguageName(enteringEmbeddedMode);
if (enteringEmbeddedLanguageId) {
enteringEmbeddedMode = enteringEmbeddedLanguageId;
}
// support language names, mime types, and language ids
const languageId = (
this._languageService.getLanguageIdForLanguageName(enteringEmbeddedMode)
|| this._languageService.getLanguageIdForMimeType(enteringEmbeddedMode)
|| enteringEmbeddedMode
);
const embeddedModeData = this._getNestedEmbeddedModeData(enteringEmbeddedMode);
const embeddedModeData = this._getNestedEmbeddedModeData(languageId);
if (pos < lineLength) {
// there is content from the embedded mode on this line
@ -846,44 +847,24 @@ export class MonarchTokenizer implements modes.ITokenizationSupport {
return MonarchLineStateFactory.create(stack, embeddedModeData);
}
private _getNestedEmbeddedModeData(mimetypeOrModeId: string): EmbeddedModeData {
let nestedModeId = this._locateMode(mimetypeOrModeId);
if (nestedModeId) {
let tokenizationSupport = modes.TokenizationRegistry.get(nestedModeId);
if (tokenizationSupport) {
return new EmbeddedModeData(nestedModeId, tokenizationSupport.getInitialState());
}
private _getNestedEmbeddedModeData(languageId: string): EmbeddedModeData {
if (!this._languageService.isRegisteredLanguageId(languageId)) {
return new EmbeddedModeData(languageId, NULL_STATE);
}
return new EmbeddedModeData(nestedModeId || NULL_MODE_ID, NULL_STATE);
}
private _locateMode(mimetypeOrModeId: string): string | null {
if (!mimetypeOrModeId) {
return null;
}
const isRegisteredLanguageId = this._languageService.isRegisteredLanguageId(mimetypeOrModeId);
const isRegisteredMimeType = this._languageService.isRegisteredMimeType(mimetypeOrModeId);
if (!isRegisteredLanguageId && !isRegisteredMimeType) {
return null;
}
if (mimetypeOrModeId === this._languageId) {
// embedding myself...
return mimetypeOrModeId;
}
const languageId = this._languageService.getModeId(mimetypeOrModeId);
if (languageId) {
if (languageId !== this._languageId) {
// Fire mode loading event
this._languageService.triggerMode(languageId);
this._embeddedModes[languageId] = true;
}
return languageId;
}
const tokenizationSupport = modes.TokenizationRegistry.get(languageId);
if (tokenizationSupport) {
return new EmbeddedModeData(languageId, tokenizationSupport.getInitialState());
}
return new EmbeddedModeData(languageId || NULL_MODE_ID, NULL_STATE);
}
}
/**

View file

@ -469,7 +469,7 @@ suite('ModelSemanticColoring', () => {
}
}));
const textModel = disposables.add(modelService.createModel('Hello world', languageService.create('testMode')));
const textModel = disposables.add(modelService.createModel('Hello world', languageService.createById('testMode')));
// wait for the provider to be called
await inFirstCall.wait();
@ -532,7 +532,7 @@ suite('ModelSemanticColoring', () => {
return result;
}
const textModel = modelService.createModel('Hello world 2', languageService.create('testMode2'));
const textModel = modelService.createModel('Hello world 2', languageService.createById('testMode2'));
try {
let result = await getDocumentSemanticTokens(textModel, null, null, CancellationToken.None);
assert.ok(result, `We should have tokens (1)`);

View file

@ -32,7 +32,7 @@ suite('TextResourceConfigurationService - Update', () => {
setup(() => {
const instantiationService = new TestInstantiationService();
instantiationService.stub(IModelService, <Partial<IModelService>>{ getModel() { return null; } });
instantiationService.stub(ILanguageService, <Partial<ILanguageService>>{ getModeIdByFilepathOrFirstLine() { return language; } });
instantiationService.stub(ILanguageService, <Partial<ILanguageService>>{ getLanguageIdByFilepathOrFirstLine() { return language; } });
instantiationService.stub(IConfigurationService, configurationService);
testObject = instantiationService.createInstance(TextResourceConfigurationService);
});

View file

@ -9,6 +9,7 @@ import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
export function testViewModel(text: string[], options: IEditorOptions, callback: (viewModel: ViewModel, model: TextModel) => void): void {
const EDITOR_ID = 1;
@ -16,7 +17,7 @@ export function testViewModel(text: string[], options: IEditorOptions, callback:
const configuration = new TestConfiguration(options);
const model = createTextModel(text.join('\n'));
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(configuration.options);
const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!, new TestLanguageConfigurationService());
callback(viewModel, model);

View file

@ -20,6 +20,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { IFileService } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { join } from 'vs/base/common/path';
import { VSBuffer } from 'vs/base/common/buffer';
function isSilentKeyCode(keyCode: KeyCode) {
return keyCode < KeyCode.Digit0;
@ -37,7 +41,9 @@ export class Driver implements IDriver, IWindowDriverRegistry {
private windowServer: IPCServer,
private options: IDriverOptions,
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IFileService private readonly fileService: IFileService,
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService
) { }
async registerWindowDriver(windowId: number): Promise<IDriverOptions> {
@ -74,7 +80,14 @@ export class Driver implements IDriver, IWindowDriverRegistry {
}
async stopTracing(windowId: number, name: string, persist: boolean): Promise<void> {
// ignore - tracing is not implemented yet
if (!persist) {
return;
}
const raw = await this.capturePage(windowId);
const buffer = Buffer.from(raw, 'base64');
await this.fileService.writeFile(URI.file(join(this.environmentMainService.logsPath, `${name}.png`)), VSBuffer.wrap(buffer));
}
async reloadWindow(windowId: number): Promise<void> {

View file

@ -440,21 +440,21 @@ export class FileService extends Disposable implements IFileService {
return stat;
}
async readFile(resource: URI, options?: IReadFileOptions): Promise<IFileContent> {
async readFile(resource: URI, options?: IReadFileOptions, token?: CancellationToken): Promise<IFileContent> {
const provider = await this.withReadProvider(resource);
if (options?.atomic) {
return this.doReadFileAtomic(provider, resource, options);
return this.doReadFileAtomic(provider, resource, options, token);
}
return this.doReadFile(provider, resource, options);
return this.doReadFile(provider, resource, options, token);
}
private async doReadFileAtomic(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions): Promise<IFileContent> {
private async doReadFileAtomic(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions, token?: CancellationToken): Promise<IFileContent> {
return new Promise<IFileContent>((resolve, reject) => {
this.writeQueue.queueFor(resource, this.getExtUri(provider).providerExtUri).queue(async () => {
try {
const content = await this.doReadFile(provider, resource, options);
const content = await this.doReadFile(provider, resource, options, token);
resolve(content);
} catch (error) {
reject(error);
@ -463,7 +463,7 @@ export class FileService extends Disposable implements IFileService {
});
}
private async doReadFile(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions): Promise<IFileContent> {
private async doReadFile(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileOptions, token?: CancellationToken): Promise<IFileContent> {
const stream = await this.doReadFileStream(provider, resource, {
...options,
// optimization: since we know that the caller does not
@ -472,7 +472,7 @@ export class FileService extends Disposable implements IFileService {
// has (open, read, close) if the provider supports
// unbuffered reading.
preferUnbuffered: true
});
}, token);
return {
...stream,
@ -480,19 +480,23 @@ export class FileService extends Disposable implements IFileService {
};
}
async readFileStream(resource: URI, options?: IReadFileStreamOptions): Promise<IFileStreamContent> {
async readFileStream(resource: URI, options?: IReadFileStreamOptions, token?: CancellationToken): Promise<IFileStreamContent> {
const provider = await this.withReadProvider(resource);
return this.doReadFileStream(provider, resource, options);
return this.doReadFileStream(provider, resource, options, token);
}
private async doReadFileStream(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileStreamOptions & { preferUnbuffered?: boolean; }): Promise<IFileStreamContent> {
private async doReadFileStream(provider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability | IFileSystemProviderWithFileReadStreamCapability, resource: URI, options?: IReadFileStreamOptions & { preferUnbuffered?: boolean; }, token?: CancellationToken): Promise<IFileStreamContent> {
// install a cancellation token that gets cancelled
// when any error occurs. this allows us to resolve
// the content of the file while resolving metadata
// but still cancel the operation in certain cases.
const cancellableSource = new CancellationTokenSource();
//
// in addition, we pass the optional token in that
// we got from the outside to even allow for external
// cancellation of the read operation.
const cancellableSource = new CancellationTokenSource(token);
// validate read operation
const statPromise = this.validateReadFile(resource, options).then(stat => stat, error => {

View file

@ -136,12 +136,12 @@ export interface IFileService {
/**
* Read the contents of the provided resource unbuffered.
*/
readFile(resource: URI, options?: IReadFileOptions): Promise<IFileContent>;
readFile(resource: URI, options?: IReadFileOptions, token?: CancellationToken): Promise<IFileContent>;
/**
* Read the contents of the provided resource buffered as stream.
*/
readFileStream(resource: URI, options?: IReadFileStreamOptions): Promise<IFileStreamContent>;
readFileStream(resource: URI, options?: IReadFileStreamOptions, token?: CancellationToken): Promise<IFileStreamContent>;
/**
* Updates the content replacing its previous value.

View file

@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { DeferredPromise, timeout } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { consumeStream, newWriteableStream, ReadableStreamEvents } from 'vs/base/common/stream';
import { URI } from 'vs/base/common/uri';
@ -299,4 +299,64 @@ suite('File Service', () => {
disposable.dispose();
}
test('readFile/readFileStream supports cancellation (https://github.com/microsoft/vscode/issues/138805)', async () => {
const service = new FileService(new NullLogService());
let readFileStreamReady: DeferredPromise<void> | undefined = undefined;
const provider = new class extends NullFileSystemProvider {
override async stat(resource: URI): Promise<IStat> {
return {
mtime: Date.now(),
ctime: Date.now(),
size: 100,
type: FileType.File
};
}
readFileStream(resource: URI, opts: FileReadStreamOptions, token: CancellationToken): ReadableStreamEvents<Uint8Array> {
const stream = newWriteableStream<Uint8Array>(chunk => chunk[0]);
token.onCancellationRequested(() => {
stream.error(new Error('Expected cancellation'));
stream.end();
});
readFileStreamReady!.complete();
return stream;
}
};
const disposable = service.registerProvider('test', provider);
provider.setCapabilities(FileSystemProviderCapabilities.FileReadStream);
let e1;
try {
const cts = new CancellationTokenSource();
readFileStreamReady = new DeferredPromise();
const promise = service.readFile(URI.parse('test://foo/bar'), undefined, cts.token);
await Promise.all([readFileStreamReady.p.then(() => cts.cancel()), promise]);
} catch (error) {
e1 = error;
}
assert.ok(e1);
let e2;
try {
const cts = new CancellationTokenSource();
readFileStreamReady = new DeferredPromise();
const stream = await service.readFileStream(URI.parse('test://foo/bar'), undefined, cts.token);
await Promise.all([readFileStreamReady.p.then(() => cts.cancel()), consumeStream(stream.value, chunk => chunk[0])]);
} catch (error) {
e2 = error;
}
assert.ok(e2);
disposable.dispose();
});
});

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { iconRegistry } from 'vs/base/common/codicons';
import { Codicon } from 'vs/base/common/codicons';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { OperatingSystem } from 'vs/base/common/platform';
import { localize } from 'vs/nls';
@ -27,8 +27,8 @@ const terminalProfileBaseProperties: IJSONSchemaMap = {
icon: {
description: localize('terminalProfile.icon', 'A codicon ID to associate with this terminal.'),
type: 'string',
enum: Array.from(iconRegistry.all, icon => icon.id),
markdownEnumDescriptions: Array.from(iconRegistry.all, icon => `$(${icon.id})`),
enum: Array.from(Codicon.getAll(), icon => icon.id),
markdownEnumDescriptions: Array.from(Codicon.getAll(), icon => `$(${icon.id})`),
},
color: {
description: localize('terminalProfile.color', 'A theme color ID to associate with this terminal.'),
@ -448,7 +448,7 @@ const terminalPlatformConfiguration: IConfigurationNode = {
default: true
},
[TerminalSettingId.IgnoreProcessNames]: {
description: localize('terminal.integrated.confirmIgnoreProcesses', "Configurable to provide a custom setting to ignore processes"),
description: localize('terminal.integrated.confirmIgnoreProcesses', "A set of process names to ignore when using the {0} setting.", '`terminal.integrated.confirmOnKill`'),
type: 'array',
items: {
type: 'string',

View file

@ -172,7 +172,7 @@ async function transformToTerminalProfiles(
} else {
originalPaths = Array.isArray(profile.path) ? profile.path : [profile.path];
args = isWindows ? profile.args : Array.isArray(profile.args) ? profile.args : undefined;
icon = validateIcon(profile.icon) || undefined;
icon = validateIcon(profile.icon);
}
const paths = (await variableResolver?.(originalPaths)) || originalPaths.slice();
@ -267,7 +267,8 @@ async function getWslProfiles(wslPath: string, defaultProfileName: string | unde
path: wslPath,
args: [`-d`, `${distroName}`],
isDefault: profileName === defaultProfileName,
icon: getWslIcon(distroName)
icon: getWslIcon(distroName),
isAutoDetected: true
};
// Add the profile
profiles.push(profile);
@ -327,6 +328,7 @@ function applyConfigProfilesToMap(configProfiles: { [key: string]: IUnresolvedTe
if (value === null || (!('path' in value) && !('source' in value))) {
profilesMap.delete(profileName);
} else {
value.icon = value.icon || profilesMap.get(profileName)?.icon;
profilesMap.set(profileName, value);
}
}

View file

@ -6,7 +6,6 @@
import { asCSSPropertyValue, asCSSUrl } from 'vs/base/browser/dom';
import { Emitter, Event } from 'vs/base/common/event';
import { getIconRegistry, IconContribution, IconFontContribution } from 'vs/platform/theme/common/iconRegistry';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
export interface IIconsStyleSheet {
@ -24,13 +23,9 @@ export function getIconsStyleSheet(): IIconsStyleSheet {
getCSS() {
const usedFontIds: { [id: string]: IconFontContribution } = {};
const formatIconRule = (contribution: IconContribution): string | undefined => {
let definition = contribution.defaults;
while (ThemeIcon.isThemeIcon(definition)) {
const c = iconRegistry.getIcon(definition.id);
if (!c) {
return undefined;
}
definition = c.defaults;
const definition = IconContribution.getDefinition(contribution, iconRegistry);
if (!definition) {
return undefined;
}
const fontId = definition.fontId;
if (fontId) {

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { RunOnceScheduler } from 'vs/base/common/async';
import * as Codicons from 'vs/base/common/codicons';
import { Codicon, CSSIcon } from 'vs/base/common/codicons';
import { Emitter, Event } from 'vs/base/common/event';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { URI } from 'vs/base/common/uri';
@ -27,6 +27,20 @@ export interface IconDefinition {
fontCharacter: string;
}
export namespace IconContribution {
export function getDefinition(contribution: IconContribution, registry: IIconRegistry): IconDefinition | undefined {
let definition = contribution.defaults;
while (ThemeIcon.isThemeIcon(definition)) {
const c = iconRegistry.getIcon(definition.id);
if (!c) {
return undefined;
}
definition = c.defaults;
}
return definition;
}
}
export interface IconContribution {
id: string;
description: string | undefined;
@ -124,7 +138,7 @@ class IconRegistry implements IIconRegistry {
type: 'object',
properties: {}
};
private iconReferenceSchema: IJSONSchema & { enum: string[], enumDescriptions: string[] } = { type: 'string', pattern: `^${Codicons.CSSIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] };
private iconReferenceSchema: IJSONSchema & { enum: string[], enumDescriptions: string[] } = { type: 'string', pattern: `^${CSSIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] };
private iconFontsById: { [key: string]: IconFontContribution };
@ -261,10 +275,9 @@ export function getIconRegistry(): IIconRegistry {
}
function initialize() {
for (const icon of Codicons.iconRegistry.all) {
for (const icon of Codicon.getAll()) {
iconRegistry.registerIcon(icon.id, icon.definition, icon.description);
}
Codicons.iconRegistry.onDidRegister(icon => iconRegistry.registerIcon(icon.id, icon.definition, icon.description));
}
initialize();
@ -286,10 +299,10 @@ iconRegistry.onDidChange(() => {
// common icons
export const widgetClose = registerIcon('widget-close', Codicons.Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'));
export const widgetClose = registerIcon('widget-close', Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'));
export const gotoPreviousLocation = registerIcon('goto-previous-location', Codicons.Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'));
export const gotoNextLocation = registerIcon('goto-next-location', Codicons.Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'));
export const gotoPreviousLocation = registerIcon('goto-previous-location', Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'));
export const gotoNextLocation = registerIcon('goto-next-location', Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'));
export const syncing = ThemeIcon.modify(Codicons.Codicon.sync, 'spin');
export const spinningLoading = ThemeIcon.modify(Codicons.Codicon.loading, 'spin');
export const syncing = ThemeIcon.modify(Codicon.sync, 'spin');
export const spinningLoading = ThemeIcon.modify(Codicon.loading, 'spin');

View file

@ -51,6 +51,10 @@ export namespace ThemeIcon {
return { id: name };
}
export function fromId(id: string) : ThemeIcon {
return { id };
}
export function modify(icon: ThemeIcon, modifier: 'disabled' | 'spin' | undefined): ThemeIcon {
let id = icon.id;
const tildeIndex = id.lastIndexOf('~');

View file

@ -8,6 +8,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IStringDictionary } from 'vs/base/common/collections';
import { getErrorMessage } from 'vs/base/common/errors';
import { Event } from 'vs/base/common/event';
import { toFormattedString } from 'vs/base/common/jsonFormatter';
import { compare } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@ -329,7 +330,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
}
return compare(e1.identifier.id, e2.identifier.id);
});
return format ? JSON.stringify(extensions, null, '\t') : JSON.stringify(extensions);
return format ? toFormattedString(extensions, {}) : JSON.stringify(extensions);
}
async hasLocalData(): Promise<boolean> {

View file

@ -9,6 +9,7 @@ import { IStringDictionary } from 'vs/base/common/collections';
import { getErrorMessage } from 'vs/base/common/errors';
import { Event } from 'vs/base/common/event';
import { parse } from 'vs/base/common/json';
import { toFormattedString } from 'vs/base/common/jsonFormatter';
import { isWeb } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
@ -48,7 +49,7 @@ function stringify(globalState: IGlobalState, format: boolean): string {
const storage: IStringDictionary<IStorageValue> = {};
storageKeys.forEach(key => storage[key] = globalState.storage[key]);
globalState.storage = storage;
return format ? JSON.stringify(globalState, null, '\t') : JSON.stringify(globalState);
return format ? toFormattedString(globalState, {}) : JSON.stringify(globalState);
}
const GLOBAL_STATE_DATA_VERSION = 1;

View file

@ -595,6 +595,12 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return;
}
// If we run smoke tests, we never want to show a blocking dialog
if (this.environmentMainService.driverHandle) {
this.destroyWindow(false);
return;
}
// Unresponsive
if (type === WindowError.UNRESPONSIVE) {
if (this.isExtensionDevelopmentHost || this.isExtensionTestHost || (this._win && this._win.webContents && this._win.webContents.isDevToolsOpened())) {

View file

@ -12,7 +12,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { Position as EditorPosition } from 'vs/editor/common/core/position';
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion, ITypeHierarchyItemDto } from '../common/extHost.protocol';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { ILanguageConfigurationService, LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { ILanguageService } from 'vs/editor/common/services/languageService';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
@ -34,15 +34,16 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
constructor(
extHostContext: IExtHostContext,
@ILanguageService languageService: ILanguageService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageFeatures);
this._languageService = languageService;
if (this._languageService) {
const updateAllWordDefinitions = () => {
const langWordPairs = LanguageConfigurationRegistry.getWordDefinitions();
let wordDefinitionDtos: ILanguageWordDefinitionDto[] = [];
for (const [languageId, wordDefinition] of langWordPairs) {
for (const languageId of languageService.getRegisteredLanguageIds()) {
const wordDefinition = languageConfigurationService.getLanguageConfiguration(languageId).getWordDefinition();
wordDefinitionDtos.push({
languageId: languageId,
regexSource: wordDefinition.source,
@ -51,13 +52,17 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
this._proxy.$setWordDefinitions(wordDefinitionDtos);
};
LanguageConfigurationRegistry.onDidChange((e) => {
const wordDefinition = LanguageConfigurationRegistry.getWordDefinition(e.languageId);
this._proxy.$setWordDefinitions([{
languageId: e.languageId,
regexSource: wordDefinition.source,
regexFlags: wordDefinition.flags
}]);
languageConfigurationService.onDidChange((e) => {
if (!e.languageId) {
updateAllWordDefinitions();
} else {
const wordDefinition = languageConfigurationService.getLanguageConfiguration(e.languageId).getWordDefinition();
this._proxy.$setWordDefinitions([{
languageId: e.languageId,
regexSource: wordDefinition.source,
regexFlags: wordDefinition.flags
}]);
}
});
updateAllWordDefinitions();
}

View file

@ -57,7 +57,7 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
const uri = URI.revive(resource);
const ref = await this._resolverService.createModelReference(uri);
try {
this._modelService.setMode(ref.object.textEditorModel, this._languageService.create(languageId));
this._modelService.setMode(ref.object.textEditorModel, this._languageService.createById(languageId));
} finally {
ref.dispose();
}

View file

@ -206,6 +206,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
}
set value(value: string) {
value = value ?? '';
this._proxy.$setInputBoxValue(this._sourceControlHandle, value);
this.updateValue(value);
}

View file

@ -353,7 +353,7 @@ configurationRegistry.registerConfiguration({
localize('keyboardShortcutsFormat.commandAndKeys', "Command title and keys."),
localize('keyboardShortcutsFormat.commandWithGroupAndKeys', "Command title and keys, with the command prefixed by its group.")
],
description: localize('screencastMode.keyboardShortcutsFormat', "Controls what is displayed in the keyboard overlay when showing only shortcuts."),
description: localize('screencastMode.keyboardShortcutsFormat', "Controls what is displayed in the keyboard overlay when showing shortcuts."),
default: 'commandAndKeys'
},
'screencastMode.onlyKeyboardShortcuts': {

View file

@ -1201,18 +1201,19 @@ export class ChangeModeAction extends Action {
const resource = EditorResourceAccessor.getOriginalUri(activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY });
if (resource) {
// Detect languages since we are in an untitled file
let languageId: string | undefined = withNullAsUndefined(this.languageService.getModeIdByFilepathOrFirstLine(resource, textModel.getLineContent(1)));
let languageId: string | undefined = withNullAsUndefined(this.languageService.getLanguageIdByFilepathOrFirstLine(resource, textModel.getLineContent(1)));
if (!languageId) {
detectedLanguage = await this.languageDetectionService.detectLanguage(resource);
languageId = detectedLanguage;
}
if (languageId) {
languageSelection = this.languageService.create(languageId);
languageSelection = this.languageService.createById(languageId);
}
}
}
} else {
languageSelection = this.languageService.createByLanguageName(pick.label);
const languageId = this.languageService.getLanguageIdForLanguageName(pick.label.toLowerCase());
languageSelection = this.languageService.createById(languageId);
if (resource) {
// fire and forget to not slow things down
@ -1247,7 +1248,7 @@ export class ChangeModeAction extends Action {
private configureFileAssociation(resource: URI): void {
const extension = extname(resource);
const base = basename(resource);
const currentAssociation = this.languageService.getModeIdByFilepathOrFirstLine(URI.file(base));
const currentAssociation = this.languageService.getLanguageIdByFilepathOrFirstLine(URI.file(base));
const languages = this.languageService.getRegisteredLanguageNames();
const picks: IQuickPickItem[] = languages.sort().map((lang, index) => {

View file

@ -181,29 +181,29 @@ export class TextResourceEditor extends AbstractTextResourceEditor {
return; // require a live model
}
const currentMode = textModel.getLanguageId();
if (currentMode !== PLAINTEXT_MODE_ID) {
return; // require current mode to be unspecific
const currentLanguageId = textModel.getLanguageId();
if (currentLanguageId !== PLAINTEXT_MODE_ID) {
return; // require current languageId to be unspecific
}
let candidateMode: string | undefined = undefined;
let candidateLanguageId: string | undefined = undefined;
// A mode is provided via the paste event so text was copied using
// VSCode. As such we trust this mode and use it if specific
// A languageId is provided via the paste event so text was copied using
// VSCode. As such we trust this languageId and use it if specific
if (e.languageId) {
candidateMode = e.languageId;
candidateLanguageId = e.languageId;
}
// A mode was not provided, so the data comes from outside VSCode
// We can still try to guess a good mode from the first line if
// A languageId was not provided, so the data comes from outside VSCode
// We can still try to guess a good languageId from the first line if
// the paste changed the first line
else {
candidateMode = withNullAsUndefined(this.languageService.getModeIdByFilepathOrFirstLine(textModel.uri, textModel.getLineContent(1).substr(0, ModelConstants.FIRST_LINE_DETECTION_LENGTH_LIMIT)));
candidateLanguageId = withNullAsUndefined(this.languageService.getLanguageIdByFilepathOrFirstLine(textModel.uri, textModel.getLineContent(1).substr(0, ModelConstants.FIRST_LINE_DETECTION_LENGTH_LIMIT)));
}
// Finally apply mode to model if specified
if (candidateMode !== PLAINTEXT_MODE_ID) {
this.modelService.setMode(textModel, this.languageService.create(candidateMode));
// Finally apply languageId to model if specified
if (candidateLanguageId !== PLAINTEXT_MODE_ID) {
this.modelService.setMode(textModel, this.languageService.createById(candidateLanguageId));
}
}
}

View file

@ -41,13 +41,13 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IProductService } from 'vs/platform/product/common/productService';
import { Schemas } from 'vs/base/common/network';
import { withNullAsUndefined } from 'vs/base/common/types';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { Codicon } from 'vs/base/common/codicons';
import { getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
import { getIconRegistry, registerIcon } from 'vs/platform/theme/common/iconRegistry';
const layoutControlIcon = registerIcon('layout-control', Codicon.layout, localize('layoutControlIcon', "Icon for the layout control menu found in the title bar."));
@ -380,13 +380,10 @@ export class TitlebarPart extends Part implements ITitleService {
if (isWeb) {
const homeIndicator = this.environmentService.options?.homeIndicator;
if (homeIndicator) {
let codicon = iconRegistry.get(homeIndicator.icon);
if (!codicon) {
codicon = Codicon.code;
}
const icon: ThemeIcon = getIconRegistry().getIcon(homeIndicator.icon) ? { id: homeIndicator.icon } : Codicon.code;
this.appIcon.setAttribute('href', homeIndicator.href);
this.appIcon.classList.add(...codicon.classNamesArray);
this.appIcon.classList.add(...ThemeIcon.asClassNameArray(icon));
this.appIconBadge = document.createElement('div');
this.appIconBadge.classList.add('home-bar-icon-badge');
this.appIcon.appendChild(this.appIconBadge);

View file

@ -95,7 +95,7 @@ export class BaseTextEditorModel extends EditorModel implements ITextEditorModel
return;
}
this.modelService.setMode(this.textEditorModel, this.languageService.create(mode));
this.modelService.setMode(this.textEditorModel, this.languageService.createById(mode));
}
getMode(): string | undefined {
@ -179,7 +179,7 @@ export class BaseTextEditorModel extends EditorModel implements ITextEditorModel
}
// otherwise take the preferred mode for granted
return languageService.create(preferredMode);
return languageService.createById(preferredMode);
}
/**
@ -197,7 +197,7 @@ export class BaseTextEditorModel extends EditorModel implements ITextEditorModel
// mode (only if specific and changed)
if (preferredMode && preferredMode !== PLAINTEXT_MODE_ID && this.textEditorModel.getLanguageId() !== preferredMode) {
this.modelService.setMode(this.textEditorModel, this.languageService.create(preferredMode));
this.modelService.setMode(this.textEditorModel, this.languageService.createById(preferredMode));
}
}

View file

@ -66,7 +66,6 @@ export class ResourceContextKey implements IContextKey<URI> {
this._isFileSystemResource.set(Boolean(resource && _fileService.hasProvider(resource)));
}));
this._disposables.add(_languageService.onDidEncounterLanguage(this._setLangId, this));
this._disposables.add(_modelService.onModelAdded(model => {
if (isEqual(model.uri, this.get())) {
this._setLangId();
@ -89,7 +88,7 @@ export class ResourceContextKey implements IContextKey<URI> {
this._langIdKey.set(null);
return;
}
const langId = this._modelService.getModel(value)?.getLanguageId() ?? this._languageService.getModeIdByFilepathOrFirstLine(value);
const langId = this._modelService.getModel(value)?.getLanguageId() ?? this._languageService.getLanguageIdByFilepathOrFirstLine(value);
this._langIdKey.set(langId);
}

View file

@ -416,7 +416,7 @@ export class BulkEditPreviewProvider implements ITextModelContentProvider {
const sourceModel = ref.object.textEditorModel;
model = this._modelService.createModel(
createTextBufferFactoryFromSnapshot(sourceModel.createSnapshot()),
this._languageService.create(sourceModel.getLanguageId()),
this._languageService.createById(sourceModel.getLanguageId()),
previewUri
);
ref.dispose();

View file

@ -14,6 +14,7 @@ import { compare } from 'vs/base/common/strings';
import { Range } from 'vs/editor/common/core/range';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { localize } from 'vs/nls';
import { CSSIcon } from 'vs/base/common/codicons';
export class Call {
constructor(
@ -118,7 +119,7 @@ export class CallRenderer implements ITreeRenderer<Call, FuzzyScore, CallRenderi
renderElement(node: ITreeNode<Call, FuzzyScore>, _index: number, template: CallRenderingTemplate): void {
const { element, filterData } = node;
const deprecated = element.item.tags?.includes(SymbolTag.Deprecated);
template.icon.className = SymbolKinds.toCssClassName(element.item.kind, true);
template.icon.classList.add('inline', ...CSSIcon.asClassNameArray(SymbolKinds.toIcon(element.item.kind)));
template.label.setLabel(
element.item.name,
element.item.detail,

View file

@ -23,6 +23,7 @@ import { IdleValue } from 'vs/base/common/async';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IOutlineComparator, OutlineConfigKeys } from 'vs/workbench/services/outline/browser/outline';
import { CSSIcon } from 'vs/base/common/codicons';
export type DocumentSymbolItem = OutlineGroup | OutlineElement;
@ -141,7 +142,7 @@ export class DocumentSymbolRenderer implements ITreeRenderer<OutlineElement, Fuz
if (this._configurationService.getValue(OutlineConfigKeys.icons)) {
// add styles for the icons
template.iconClass.className = '';
template.iconClass.classList.add(`outline-element-icon`, ...SymbolKinds.toCssClassName(element.symbol.kind, true).split(' '));
template.iconClass.classList.add('outline-element-icon', 'inline', ...CSSIcon.asClassNameArray(SymbolKinds.toIcon(element.symbol.kind)));
}
if (element.symbol.tags.indexOf(SymbolTag.Deprecated) >= 0) {
options.extraClasses!.push(`deprecated`);

View file

@ -23,6 +23,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry';
export const ctxCommentEditorFocused = new RawContextKey<boolean>('commentEditorFocused', false);
@ -44,7 +45,8 @@ export class SimpleCommentEditor extends CodeEditorWidget {
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService,
@IAccessibilityService accessibilityService: IAccessibilityService
@IAccessibilityService accessibilityService: IAccessibilityService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
) {
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
isSimpleWidget: true,
@ -57,7 +59,7 @@ export class SimpleCommentEditor extends CodeEditorWidget {
]
};
super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService);
super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService);
this._commentEditorFocused = ctxCommentEditorFocused.bindTo(contextKeyService);
this._commentEditorEmpty = CommentContextKeys.commentIsEmpty.bindTo(contextKeyService);

View file

@ -30,7 +30,7 @@ import { Range } from 'vs/editor/common/core/range';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ITextModel } from 'vs/editor/common/model';
import { CompletionContext, CompletionItem, CompletionItemInsertTextRule, CompletionItemKind, completionKindFromString, CompletionList, CompletionProviderRegistry } from 'vs/editor/common/modes';
import { CompletionContext, CompletionItem, CompletionItemInsertTextRule, CompletionItemKind, CompletionItemKinds, CompletionList, CompletionProviderRegistry } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService';
import { SuggestController } from 'vs/editor/contrib/suggest/suggestController';
@ -252,7 +252,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
suggestions.push({
label: item.label,
insertText,
kind: completionKindFromString(item.type || 'property'),
kind: CompletionItemKinds.fromString(item.type || 'property'),
filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined,
range: computeRange(item.length || overwriteBefore),
sortText: item.sortText,

View file

@ -5,7 +5,7 @@
import { URI as uri } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { guessMimeTypes, Mimes } from 'vs/base/common/mime';
import { guessMimeTypes } from 'vs/base/common/mime';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ILanguageService } from 'vs/editor/common/services/languageService';
@ -17,6 +17,7 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Range } from 'vs/editor/common/core/range';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
/**
* Debug URI format
@ -94,7 +95,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
}
const createErrModel = (errMsg?: string) => {
this.debugService.sourceIsNotAvailable(resource);
const languageSelection = this.languageService.create(Mimes.text);
const languageSelection = this.languageService.createById(PLAINTEXT_MODE_ID);
const message = errMsg
? localize('canNotResolveSourceWithError', "Could not load source '{0}': {1}.", resource.path, errMsg)
: localize('canNotResolveSource', "Could not load source '{0}'.", resource.path);
@ -134,7 +135,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
} else {
// create text model
const mime = response.body.mimeType || guessMimeTypes(resource)[0];
const languageSelection = this.languageService.create(mime);
const languageSelection = this.languageService.createByMimeType(mime);
return this.modelService.createModel(response.body.content, languageSelection, resource);
}
}

View file

@ -5,7 +5,6 @@
import 'vs/css!./media/extensionEditor';
import { localize } from 'vs/nls';
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import * as arrays from 'vs/base/common/arrays';
import { OS } from 'vs/base/common/platform';
import { Event, Emitter } from 'vs/base/common/event';
@ -23,7 +22,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
import { ExtensionsInput, IExtensionEditorOptions } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, IExtension, ExtensionContainers, ExtensionEditorTab, ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions';
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget, ExtensionWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
import { IEditorOpenContext } from 'vs/workbench/common/editor';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import {
@ -49,7 +48,6 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { getDefaultValue } from 'vs/platform/configuration/common/configurationRegistry';
import { isUndefined } from 'vs/base/common/types';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IWebviewService, IWebview, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/webview/browser/webview';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { generateUuid } from 'vs/base/common/uuid';
@ -140,8 +138,6 @@ interface IExtensionEditorTemplate {
name: HTMLElement;
preview: HTMLElement;
builtin: HTMLElement;
version: HTMLElement;
preRelease: HTMLElement;
publisher: HTMLElement;
publisherDisplayName: HTMLElement;
verifiedPublisherIcon: HTMLElement;
@ -155,6 +151,9 @@ interface IExtensionEditorTemplate {
navbar: NavBar;
content: HTMLElement;
header: HTMLElement;
extension: IExtension;
gallery: IGalleryExtension | null;
manifest: IExtensionManifest | null;
}
const enum WebviewIndex {
@ -164,8 +163,53 @@ const enum WebviewIndex {
const CONTEXT_SHOW_PRE_RELEASE_VERSION = new RawContextKey<boolean>('showPreReleaseVersion', false);
interface IExtensionEditorWidget extends IDisposable {
updateInput(extension: IExtension, gallery: IGalleryExtension | undefined, preserveFocus?: boolean): void;
abstract class ExtensionWithDifferentGalleryVersionWidget extends ExtensionWidget {
private _gallery: IGalleryExtension | null = null;
get gallery(): IGalleryExtension | null { return this._gallery; }
set gallery(gallery: IGalleryExtension | null) {
if (this.extension && gallery && !areSameExtensions(this.extension.identifier, gallery.identifier)) {
return;
}
this._gallery = gallery;
this.update();
}
}
class VersionWidget extends ExtensionWithDifferentGalleryVersionWidget {
private readonly element: HTMLElement;
constructor(container: HTMLElement) {
super();
this.element = append(container, $('code.version', { title: localize('extension version', "Extension Version") }));
this.render();
}
render(): void {
if (!this.extension) {
return;
}
this.element.textContent = `v${this.gallery ? this.gallery.version : this.extension.version}`;
}
}
class PreReleaseTextWidget extends ExtensionWithDifferentGalleryVersionWidget {
private readonly element: HTMLElement;
constructor(container: HTMLElement) {
super();
this.element = append(container, $('span.pre-release'));
this.element.textContent = localize('preRelease', "Pre-Release");
this.render();
}
render(): void {
this.element.style.display = this.isPreReleaseVersion() ? 'inherit' : 'none';
}
private isPreReleaseVersion(): boolean {
if (!this.extension) {
return false;
}
if (this.gallery) {
return this.gallery.properties.isPreReleaseVersion;
}
return !!(this.extension.local?.isPreReleaseVersion || this.extension.gallery?.properties.isPreReleaseVersion);
}
}
export class ExtensionEditor extends EditorPane {
@ -193,7 +237,6 @@ export class ExtensionEditor extends EditorPane {
private dimension: Dimension | undefined;
private showPreReleaseVersionContextKey: IContextKey<boolean> | undefined;
private readonly extensionEditorWidget: IExtensionEditorWidget;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@ -209,7 +252,6 @@ export class ExtensionEditor extends EditorPane {
@IExtensionIgnoredRecommendationsService private readonly extensionIgnoredRecommendationsService: IExtensionIgnoredRecommendationsService,
@IStorageService storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IWebviewService private readonly webviewService: IWebviewService,
@ILanguageService private readonly languageService: ILanguageService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@ -219,31 +261,6 @@ export class ExtensionEditor extends EditorPane {
this.extensionReadme = null;
this.extensionChangelog = null;
this.extensionManifest = null;
const that = this;
this.extensionEditorWidget = this._register(new class extends Disposable implements IExtensionEditorWidget {
private gallery: IGalleryExtension | undefined = undefined;
private extension: IExtension | undefined = undefined;
private updatePromise: CancelablePromise<void> | undefined;
constructor() {
super();
this._register(that.extensionsWorkbenchService.onChange(e => {
if (e && this.extension
&& areSameExtensions(this.extension.identifier, e?.identifier)
&& (!this.extension.server || this.extension.server === e.server)
&& this.extension.latestVersion !== e.latestVersion) {
this.updateInput(e, this.gallery);
}
}));
}
updateInput(extension: IExtension, gallery: IGalleryExtension | undefined, preserveFocus?: boolean): void {
this.extension = extension;
this.gallery = gallery;
if (that.template) {
this.updatePromise?.cancel();
this.updatePromise = createCancelablePromise(token => that.updateTemplate(this.extension!, this.gallery, that.template!, !!preserveFocus, token));
}
}
}());
}
override get scopedContextKeyService(): IContextKeyService | undefined {
@ -263,17 +280,17 @@ export class ExtensionEditor extends EditorPane {
const iconContainer = append(header, $('.icon-container'));
const icon = append(iconContainer, $<HTMLImageElement>('img.icon', { draggable: false }));
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, iconContainer, true);
const details = append(header, $('.details'));
const title = append(details, $('.title'));
const name = append(title, $('span.name.clickable', { title: localize('name', "Extension name"), role: 'heading', tabIndex: 0 }));
const version = append(title, $('code.version', { title: localize('extension version', "Extension Version") }));
const versionWidget = new VersionWidget(title);
const preview = append(title, $('span.preview', { title: localize('preview', "Preview") }));
preview.textContent = localize('preview', "Preview");
const preRelease = append(title, $('span.pre-release'));
preRelease.textContent = localize('preRelease', "Pre-Release");
const preReleaseWidget = new PreReleaseTextWidget(title);
const builtin = append(title, $('span.builtin'));
builtin.textContent = localize('builtin', "Built-in");
@ -282,12 +299,52 @@ export class ExtensionEditor extends EditorPane {
publisher.setAttribute('role', 'button');
const verifiedPublisherIcon = append(publisher, $(`.publisher-verified${ThemeIcon.asCSSSelector(verifiedPublisherThemeIcon)}`));
const publisherDisplayName = append(publisher, $('.publisher-name'));
const installCount = append(append(subtitle, $('.subtitle-entry')), $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 }));
const installCountWidget = this.instantiationService.createInstance(InstallCountWidget, installCount, false);
const rating = append(append(subtitle, $('.subtitle-entry')), $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 }));
rating.setAttribute('role', 'link'); // #132645
const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, rating, false);
const widgets = [
remoteBadge,
versionWidget,
preReleaseWidget,
installCountWidget,
ratingsWidget,
];
const description = append(details, $('.description'));
const installAction = this.instantiationService.createInstance(InstallDropdownAction);
const actions = [
this.instantiationService.createInstance(ReloadAction),
this.instantiationService.createInstance(ExtensionStatusLabelAction),
this.instantiationService.createInstance(UpdateAction),
this.instantiationService.createInstance(SetColorThemeAction),
this.instantiationService.createInstance(SetFileIconThemeAction),
this.instantiationService.createInstance(SetProductIconThemeAction),
this.instantiationService.createInstance(EnableDropDownAction),
this.instantiationService.createInstance(DisableDropDownAction),
this.instantiationService.createInstance(RemoteInstallAction, false),
this.instantiationService.createInstance(LocalInstallAction),
this.instantiationService.createInstance(WebInstallAction),
installAction,
this.instantiationService.createInstance(InstallingLabelAction),
this.instantiationService.createInstance(ActionWithDropDownAction, 'extensions.uninstall', UninstallAction.UninstallLabel, [
[
this.instantiationService.createInstance(UninstallAction),
this.instantiationService.createInstance(InstallAnotherVersionAction),
]
]),
this.instantiationService.createInstance(SwitchToPreReleaseVersionAction),
this.instantiationService.createInstance(SwitchToReleasedVersionAction),
this.instantiationService.createInstance(ToggleSyncExtensionAction),
new ExtensionEditorManageExtensionAction(this.scopedContextKeyService || this.contextKeyService, this.instantiationService),
];
const actionsAndStatusContainer = append(details, $('.actions-status-container'));
const extensionActionBar = this._register(new ActionBar(actionsAndStatusContainer, {
animated: false,
@ -303,6 +360,19 @@ export class ExtensionEditor extends EditorPane {
focusOnlyEnabledItems: true
}));
extensionActionBar.push(actions, { icon: true, label: true });
extensionActionBar.setFocusable(true);
// update focusable elements when the enablement of an action changes
this._register(Event.any(...actions.map(a => Event.filter(a.onDidChange, e => e.enabled !== undefined)))(() => {
extensionActionBar.setFocusable(false);
extensionActionBar.setFocusable(true);
}));
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
for (const disposable of [...actions, ...widgets, extensionContainers]) {
this._register(disposable);
}
const status = append(actionsAndStatusContainer, $('.status'));
const recommendation = append(details, $('.recommendation'));
@ -324,8 +394,6 @@ export class ExtensionEditor extends EditorPane {
header,
icon,
iconContainer,
version,
preRelease,
installCount,
name,
navbar,
@ -337,7 +405,17 @@ export class ExtensionEditor extends EditorPane {
actionsAndStatusContainer,
extensionActionBar,
status,
recommendation
recommendation,
set extension(extension: IExtension) {
extensionContainers.extension = extension;
},
set gallery(gallery: IGalleryExtension | null) {
versionWidget.gallery = gallery;
preReleaseWidget.gallery = gallery;
},
set manifest(manifest: IExtensionManifest | null) {
installAction.manifest = manifest;
}
};
}
@ -359,8 +437,7 @@ export class ExtensionEditor extends EditorPane {
await super.setInput(input, options, context, token);
this.updatePreReleaseVersionContext();
if (this.template) {
const gallery = await this.getGallery(input.extension, options?.showPreReleaseVersion);
this.extensionEditorWidget.updateInput(input.extension, gallery, options?.preserveFocus);
this.render(input.extension, this.template, !!options?.preserveFocus);
}
}
@ -368,27 +445,11 @@ export class ExtensionEditor extends EditorPane {
const currentOptions: IExtensionEditorOptions | undefined = this.options;
super.setOptions(options);
this.updatePreReleaseVersionContext();
if (this.input && currentOptions?.showPreReleaseVersion !== options?.showPreReleaseVersion) {
this.getGallery((<ExtensionsInput>this.input).extension, !!options?.showPreReleaseVersion).then(gallery => this.extensionEditorWidget.updateInput((<ExtensionsInput>this.input).extension, gallery));
if (this.input && this.template && currentOptions?.showPreReleaseVersion !== options?.showPreReleaseVersion) {
this.render((this.input as ExtensionsInput).extension, this.template, !!options?.preserveFocus);
}
}
private async getGallery(extension: IExtension, preRelease?: boolean): Promise<IGalleryExtension | undefined> {
if (isUndefined(preRelease)) {
return undefined;
}
if (preRelease === extension.gallery?.properties.isPreReleaseVersion) {
return undefined;
}
if (preRelease && !extension.hasPreReleaseVersion) {
return undefined;
}
if (!preRelease && !extension.hasReleaseVersion) {
return undefined;
}
return (await this.extensionGalleryService.query({ includePreRelease: preRelease, names: [extension.identifier.id] }, CancellationToken.None)).firstPage[0];
}
private updatePreReleaseVersionContext(): void {
let showPreReleaseVersion = (<IExtensionEditorOptions | undefined>this.options)?.showPreReleaseVersion;
if (isUndefined(showPreReleaseVersion)) {
@ -410,51 +471,52 @@ export class ExtensionEditor extends EditorPane {
}
}
private async updateTemplate(extension: IExtension, gallery: IGalleryExtension | undefined, template: IExtensionEditorTemplate, preserveFocus: boolean, token: CancellationToken): Promise<void> {
private async getGalleryVersionToShow(extension: IExtension, preRelease?: boolean): Promise<IGalleryExtension | null> {
if (isUndefined(preRelease)) {
return null;
}
if (preRelease === extension.gallery?.properties.isPreReleaseVersion) {
return null;
}
if (preRelease && !extension.hasPreReleaseVersion) {
return null;
}
if (!preRelease && !extension.hasReleaseVersion) {
return null;
}
return (await this.extensionGalleryService.query({ includePreRelease: preRelease, names: [extension.identifier.id] }, CancellationToken.None)).firstPage[0] || null;
}
private async render(extension: IExtension, template: IExtensionEditorTemplate, preserveFocus: boolean): Promise<void> {
this.activeElement = null;
this.editorLoadComplete = false;
if (this.currentIdentifier !== extension.identifier.id) {
this.initialScrollProgress.clear();
this.currentIdentifier = extension.identifier.id;
}
this.transientDisposables.clear();
this.extensionReadme = new Cache(() => extension.getReadme(!!this.showPreReleaseVersionContextKey?.get(), token));
this.extensionChangelog = new Cache(() => extension.getChangelog(!!this.showPreReleaseVersionContextKey?.get(), token));
this.extensionManifest = new Cache(() => extension.getManifest(!!this.showPreReleaseVersionContextKey?.get(), token));
const token = this.transientDisposables.add(new CancellationTokenSource()).token;
const gallery = await this.getGalleryVersionToShow(extension, (this.options as IExtensionEditorOptions)?.showPreReleaseVersion);
if (token.isCancellationRequested) {
return;
}
this.extensionReadme = new Cache(() => gallery ? this.extensionGalleryService.getReadme(gallery, token) : extension.getReadme(token));
this.extensionChangelog = new Cache(() => gallery ? this.extensionGalleryService.getChangelog(gallery, token) : extension.getChangelog(token));
this.extensionManifest = new Cache(() => gallery ? this.extensionGalleryService.getManifest(gallery, token) : extension.getManifest(token));
template.extension = extension;
template.gallery = gallery;
template.manifest = null;
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, template.iconContainer, true);
this.transientDisposables.add(addDisposableListener(template.icon, 'error', () => template.icon.src = extension.iconUrlFallback, { once: true }));
template.icon.src = extension.iconUrl;
template.name.textContent = extension.displayName;
template.version.textContent = `v${gallery ? gallery.version : extension.version}`;
template.name.classList.toggle('clickable', !!extension.url);
template.preview.style.display = extension.preview ? 'inherit' : 'none';
template.preRelease.style.display = (gallery ? gallery.properties.isPreReleaseVersion : (extension.local?.isPreReleaseVersion || extension.gallery?.properties.isPreReleaseVersion)) ? 'inherit' : 'none';
template.builtin.style.display = extension.isBuiltin ? 'inherit' : 'none';
template.description.textContent = extension.description;
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
let recommendationsData = {};
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
recommendationsData = { recommendationReason: extRecommendations[extension.identifier.id.toLowerCase()].reasonId };
}
/* __GDPR__
"extensionGallery:openExtension" : {
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"${include}": [
"${GalleryExtensionTelemetryData}"
]
}
*/
this.telemetryService.publicLog('extensionGallery:openExtension', { ...extension.telemetryData, ...recommendationsData });
template.name.classList.toggle('clickable', !!extension.url);
// subtitle
template.publisher.classList.toggle('clickable', !!extension.url);
template.publisherDisplayName.textContent = extension.publisherDisplayName;
@ -462,7 +524,6 @@ export class ExtensionEditor extends EditorPane {
template.publisher.title = extension.publisherDomain?.link ? localize('publisher verified tooltip', "This publisher has verified ownership of {0}", URI.parse(extension.publisherDomain.link).authority) : '';
template.installCount.parentElement?.classList.toggle('hide', !extension.url);
template.rating.parentElement?.classList.toggle('hide', !extension.url);
template.rating.classList.toggle('clickable', !!extension.url);
@ -476,82 +537,50 @@ export class ExtensionEditor extends EditorPane {
}));
}
const [colorThemes, fileIconThemes, productIconThemes] = await Promise.all([
this.workbenchThemeService.getColorThemes(),
this.workbenchThemeService.getFileIconThemes(),
this.workbenchThemeService.getProductIconThemes(),
]);
if (token.isCancellationRequested) {
return;
}
const widgets = [
remoteBadge,
this.instantiationService.createInstance(InstallCountWidget, template.installCount, false),
this.instantiationService.createInstance(RatingsWidget, template.rating, false)
];
const reloadAction = this.instantiationService.createInstance(ReloadAction);
const combinedInstallAction = this.instantiationService.createInstance(InstallDropdownAction);
const actions = [
reloadAction,
this.instantiationService.createInstance(ExtensionStatusLabelAction),
this.instantiationService.createInstance(UpdateAction),
this.instantiationService.createInstance(SetColorThemeAction, colorThemes),
this.instantiationService.createInstance(SetFileIconThemeAction, fileIconThemes),
this.instantiationService.createInstance(SetProductIconThemeAction, productIconThemes),
this.instantiationService.createInstance(EnableDropDownAction),
this.instantiationService.createInstance(DisableDropDownAction),
this.instantiationService.createInstance(RemoteInstallAction, false),
this.instantiationService.createInstance(LocalInstallAction),
this.instantiationService.createInstance(WebInstallAction),
combinedInstallAction,
this.instantiationService.createInstance(InstallingLabelAction),
this.instantiationService.createInstance(ActionWithDropDownAction, 'extensions.uninstall', UninstallAction.UninstallLabel, [
[
this.instantiationService.createInstance(UninstallAction),
this.instantiationService.createInstance(InstallAnotherVersionAction),
]
]),
this.instantiationService.createInstance(SwitchToPreReleaseVersionAction),
this.instantiationService.createInstance(SwitchToReleasedVersionAction),
this.instantiationService.createInstance(ToggleSyncExtensionAction),
new ExtensionEditorManageExtensionAction(this.scopedContextKeyService || this.contextKeyService, this.instantiationService),
];
const extensionStatus = this.instantiationService.createInstance(ExtensionStatusAction);
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, extensionStatus]);
extensionContainers.extension = extension;
template.extensionActionBar.clear();
template.extensionActionBar.push(actions, { icon: true, label: true });
template.extensionActionBar.setFocusable(true);
// update focusable elements when the enablement of an action changes
this.transientDisposables.add(Event.any(...actions.map(a => Event.filter(a.onDidChange, e => e.enabled !== undefined)))(() => {
template.extensionActionBar.setFocusable(false);
template.extensionActionBar.setFocusable(true);
}));
for (const disposable of [...actions, ...widgets, extensionContainers]) {
this.transientDisposables.add(disposable);
}
this.setStatus(extension, extensionStatus, template);
this.setStatus(extension, template);
this.setRecommendationText(extension, template);
template.content.innerText = ''; // Clear content before setting navbar actions.
template.navbar.clear();
if (extension.hasReadme()) {
template.navbar.push(ExtensionEditorTab.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
}
const manifest = await this.extensionManifest.get().promise;
if (token.isCancellationRequested) {
return;
}
if (manifest) {
combinedInstallAction.manifest = manifest;
template.manifest = manifest;
}
this.renderNavbar(extension, manifest, template, preserveFocus);
// report telemetry
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
let recommendationsData = {};
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
recommendationsData = { recommendationReason: extRecommendations[extension.identifier.id.toLowerCase()].reasonId };
}
/* __GDPR__
"extensionGallery:openExtension" : {
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"${include}": [
"${GalleryExtensionTelemetryData}"
]
}
*/
this.telemetryService.publicLog('extensionGallery:openExtension', { ...extension.telemetryData, ...recommendationsData });
this.editorLoadComplete = true;
}
private renderNavbar(extension: IExtension, manifest: IExtensionManifest | null, template: IExtensionEditorTemplate, preserveFocus: boolean): void {
template.content.innerText = '';
template.navbar.clear();
if (this.currentIdentifier !== extension.identifier.id) {
this.initialScrollProgress.clear();
this.currentIdentifier = extension.identifier.id;
}
if (extension.hasReadme()) {
template.navbar.push(ExtensionEditorTab.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
}
if (manifest && manifest.contributes) {
template.navbar.push(ExtensionEditorTab.Contributions, localize('contributions', "Feature Contributions"), localize('contributionstooltip', "Lists contributions to VS Code by this extension"));
@ -582,13 +611,12 @@ export class ExtensionEditor extends EditorPane {
this.onNavbarChange(extension, { id: template.navbar.currentId, focus: !preserveFocus }, template);
}
template.navbar.onChange(e => this.onNavbarChange(extension, e, template), this, this.transientDisposables);
this.editorLoadComplete = true;
}
private setStatus(extension: IExtension, extensionStatus: ExtensionStatusAction, template: IExtensionEditorTemplate): void {
const disposables = new DisposableStore();
this.transientDisposables.add(disposables);
private setStatus(extension: IExtension, template: IExtensionEditorTemplate): void {
const disposables = this.transientDisposables.add(new DisposableStore());
const extensionStatus = disposables.add(this.instantiationService.createInstance(ExtensionStatusAction));
extensionStatus.extension = extension;
const updateStatus = (layout: boolean) => {
disposables.clear();
reset(template.status);

View file

@ -14,8 +14,8 @@ import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsServi
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/services/output/common/output';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, DefaultViewsContext, ExtensionsSortByContext, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab } from 'vs/workbench/contrib/extensions/common/extensions';
import { ReinstallAction, InstallSpecificVersionOfExtensionAction, ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, PromptExtensionInstallFailureAction, SearchExtensionsAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, DefaultViewsContext, ExtensionsSortByContext, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP } from 'vs/workbench/contrib/extensions/common/extensions';
import { ReinstallAction, InstallSpecificVersionOfExtensionAction, ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, PromptExtensionInstallFailureAction, SearchExtensionsAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, SetColorThemeAction, SetFileIconThemeAction, SetProductIconThemeAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor';
import { StatusUpdater, MaliciousExtensionChecker, ExtensionsViewletViewsContribution, ExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet';
@ -1165,12 +1165,76 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
// Extension Context Menu
private registerContextMenuActions(): void {
this.registerExtensionAction({
id: SetColorThemeAction.ID,
title: SetColorThemeAction.TITLE,
menu: {
id: MenuId.ExtensionContext,
group: THEME_ACTIONS_GROUP,
order: 0,
when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasColorThemes'))
},
run: async (accessor: ServicesAccessor, extensionId: string) => {
const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);
const instantiationService = accessor.get(IInstantiationService);
const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));
if (extension) {
const action = instantiationService.createInstance(SetColorThemeAction);
action.extension = extension;
return action.run();
}
}
});
this.registerExtensionAction({
id: SetFileIconThemeAction.ID,
title: SetFileIconThemeAction.TITLE,
menu: {
id: MenuId.ExtensionContext,
group: THEME_ACTIONS_GROUP,
order: 0,
when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasFileIconThemes'))
},
run: async (accessor: ServicesAccessor, extensionId: string) => {
const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);
const instantiationService = accessor.get(IInstantiationService);
const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));
if (extension) {
const action = instantiationService.createInstance(SetFileIconThemeAction);
action.extension = extension;
return action.run();
}
}
});
this.registerExtensionAction({
id: SetProductIconThemeAction.ID,
title: SetProductIconThemeAction.TITLE,
menu: {
id: MenuId.ExtensionContext,
group: THEME_ACTIONS_GROUP,
order: 0,
when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasProductIconThemes'))
},
run: async (accessor: ServicesAccessor, extensionId: string) => {
const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);
const instantiationService = accessor.get(IInstantiationService);
const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));
if (extension) {
const action = instantiationService.createInstance(SetProductIconThemeAction);
action.extension = extension;
return action.run();
}
}
});
this.registerExtensionAction({
id: 'workbench.extensions.action.showPreReleaseVersion',
title: { value: localize('show pre-release version', "Show Pre-Release Version"), original: 'Show Pre-Release Version' },
menu: {
id: MenuId.ExtensionContext,
group: '0_install',
group: INSTALL_ACTIONS_GROUP,
order: 0,
when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.not('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))
},
@ -1185,7 +1249,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
title: { value: localize('show released version', "Show Release Version"), original: 'Show Release Version' },
menu: {
id: MenuId.ExtensionContext,
group: '0_install',
group: INSTALL_ACTIONS_GROUP,
order: 1,
when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.has('extensionHasReleaseVersion'), ContextKeyExpr.has('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))
},
@ -1200,7 +1264,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
title: SwitchToPreReleaseVersionAction.TITLE,
menu: {
id: MenuId.ExtensionContext,
group: '0_install',
group: INSTALL_ACTIONS_GROUP,
order: 2,
when: ContextKeyExpr.and(ContextKeyExpr.not('installedExtensionIsPreReleaseVersion'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))
},
@ -1218,7 +1282,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
title: SwitchToReleasedVersionAction.TITLE,
menu: {
id: MenuId.ExtensionContext,
group: '0_install',
group: INSTALL_ACTIONS_GROUP,
order: 3,
when: ContextKeyExpr.and(ContextKeyExpr.has('installedExtensionIsPreReleaseVersion'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.has('extensionHasReleaseVersion'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))
},

View file

@ -12,7 +12,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import * as json from 'vs/base/common/json';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { dispose } from 'vs/base/common/lifecycle';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP } from 'vs/workbench/contrib/extensions/common/extensions';
import { ExtensionsConfigurationInitialContent } from 'vs/workbench/contrib/extensions/common/extensionsFileTemplate';
import { IGalleryExtension, IExtensionGalleryService, ILocalExtension, InstallOptions, InstallOperation, TargetPlatformToString, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
@ -236,7 +236,7 @@ export abstract class AbstractInstallAction extends ExtensionAction {
static readonly Class = `${ExtensionAction.LABEL_ACTION_CLASS} prominent install`;
protected _manifest: IExtensionManifest | null = null;
set manifest(manifest: IExtensionManifest) {
set manifest(manifest: IExtensionManifest | null) {
this._manifest = manifest;
this.updateLabel();
}
@ -284,9 +284,7 @@ export abstract class AbstractInstallAction extends ExtensionAction {
alert(localize('installExtensionComplete', "Installing extension {0} is completed.", this.extension.displayName));
const runningExtension = await this.getRunningExtension(extension.local);
if (runningExtension && !(runningExtension.activationEvents && runningExtension.activationEvents.some(activationEent => activationEent.startsWith('onLanguage')))) {
let action = await SetColorThemeAction.create(this.workbenchThemeService, this.instantiationService, extension)
|| await SetFileIconThemeAction.create(this.workbenchThemeService, this.instantiationService, extension)
|| await SetProductIconThemeAction.create(this.workbenchThemeService, this.instantiationService, extension);
const action = await this.getThemeAction(extension);
if (action) {
try {
return action.run({ showCurrentTheme: true, ignoreFocusLost: true });
@ -299,6 +297,22 @@ export abstract class AbstractInstallAction extends ExtensionAction {
}
private async getThemeAction(extension: IExtension): Promise<IAction | undefined> {
const colorThemes = await this.workbenchThemeService.getColorThemes();
if (colorThemes.some(theme => isThemeFromExtension(theme, extension))) {
return this.instantiationService.createInstance(SetColorThemeAction);
}
const fileIconThemes = await this.workbenchThemeService.getFileIconThemes();
if (fileIconThemes.some(theme => isThemeFromExtension(theme, extension))) {
return this.instantiationService.createInstance(SetFileIconThemeAction);
}
const productIconThemes = await this.workbenchThemeService.getProductIconThemes();
if (productIconThemes.some(theme => isThemeFromExtension(theme, extension))) {
return this.instantiationService.createInstance(SetProductIconThemeAction);
}
return undefined;
}
private async install(extension: IExtension): Promise<IExtension | undefined> {
const installOptions = this.getInstallOptions();
try {
@ -447,9 +461,8 @@ export class InstallAndSyncAction extends AbstractInstallAction {
export class InstallDropdownAction extends ActionWithDropDownAction {
set manifest(manifest: IExtensionManifest) {
set manifest(manifest: IExtensionManifest | null) {
this.extensionActions.forEach(a => (<AbstractInstallAction>a).manifest = manifest);
this.extensionActions.forEach(a => a.update());
this.update();
}
@ -854,11 +867,12 @@ export class DropDownMenuActionViewItem extends ActionViewItem {
}
}
function getContextMenuActionsGroups(extension: IExtension | undefined | null, contextKeyService: IContextKeyService, instantiationService: IInstantiationService): [string, Array<MenuItemAction | SubmenuItemAction>][] {
return instantiationService.invokeFunction(accessor => {
async function getContextMenuActionsGroups(extension: IExtension | undefined | null, contextKeyService: IContextKeyService, instantiationService: IInstantiationService): Promise<[string, Array<MenuItemAction | SubmenuItemAction>][]> {
return instantiationService.invokeFunction(async accessor => {
const menuService = accessor.get(IMenuService);
const extensionRecommendationsService = accessor.get(IExtensionRecommendationsService);
const extensionIgnoredRecommendationsService = accessor.get(IExtensionIgnoredRecommendationsService);
const workbenchThemeService = accessor.get(IWorkbenchThemeService);
const cksOverlay: [string, any][] = [];
if (extension) {
@ -875,6 +889,11 @@ function getContextMenuActionsGroups(extension: IExtension | undefined | null, c
cksOverlay.push(['galleryExtensionIsPreReleaseVersion', !!extension.gallery?.properties.isPreReleaseVersion]);
cksOverlay.push(['extensionHasPreReleaseVersion', extension.hasPreReleaseVersion]);
cksOverlay.push(['extensionHasReleaseVersion', extension.hasReleaseVersion]);
const [colorThemes, fileIconThemes, productIconThemes] = await Promise.all([workbenchThemeService.getColorThemes(), workbenchThemeService.getFileIconThemes(), workbenchThemeService.getProductIconThemes()]);
cksOverlay.push(['extensionHasColorThemes', colorThemes.some(theme => isThemeFromExtension(theme, extension))]);
cksOverlay.push(['extensionHasFileIconThemes', fileIconThemes.some(theme => isThemeFromExtension(theme, extension))]);
cksOverlay.push(['extensionHasProductIconThemes', productIconThemes.some(theme => isThemeFromExtension(theme, extension))]);
}
const menu = menuService.createMenu(MenuId.ExtensionContext, contextKeyService.createOverlay(cksOverlay));
@ -898,8 +917,8 @@ function toActions(actionsGroups: [string, Array<MenuItemAction | SubmenuItemAct
}
export function getContextMenuActions(extension: IExtension | undefined | null, contextKeyService: IContextKeyService, instantiationService: IInstantiationService): IAction[][] {
const actionsGroups = getContextMenuActionsGroups(extension, contextKeyService, instantiationService);
export async function getContextMenuActions(extension: IExtension | undefined | null, contextKeyService: IContextKeyService, instantiationService: IInstantiationService): Promise<IAction[][]> {
const actionsGroups = await getContextMenuActionsGroups(extension, contextKeyService, instantiationService);
return toActions(actionsGroups, instantiationService);
}
@ -913,7 +932,6 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
constructor(
@IInstantiationService instantiationService: IInstantiationService,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
@ -926,27 +944,21 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
async getActionGroups(runningExtensions: IExtensionDescription[]): Promise<IAction[][]> {
const groups: IAction[][] = [];
if (this.extension) {
const actions = await Promise.all([
SetColorThemeAction.create(this.workbenchThemeService, this.instantiationService, this.extension),
SetFileIconThemeAction.create(this.workbenchThemeService, this.instantiationService, this.extension),
SetProductIconThemeAction.create(this.workbenchThemeService, this.instantiationService, this.extension)
]);
const themesGroup: ExtensionAction[] = [];
for (let action of actions) {
if (action) {
themesGroup.push(action);
}
}
if (themesGroup.length) {
groups.push(themesGroup);
const contextMenuActionsGroups = await getContextMenuActionsGroups(this.extension, this.contextKeyService, this.instantiationService);
const themeActions: IAction[] = [], installActions: IAction[] = [], otherActionGroups: IAction[][] = [];
for (const [group, actions] of contextMenuActionsGroups) {
if (group === INSTALL_ACTIONS_GROUP) {
installActions.push(...toActions([[group, actions]], this.instantiationService)[0]);
} else if (group === THEME_ACTIONS_GROUP) {
themeActions.push(...toActions([[group, actions]], this.instantiationService)[0]);
} else {
otherActionGroups.push(...toActions([[group, actions]], this.instantiationService));
}
}
const contextMenuActionsGroups = getContextMenuActionsGroups(this.extension, this.contextKeyService, this.instantiationService);
const installActions = toActions(contextMenuActionsGroups.filter(([group]) => group === '0_install'), this.instantiationService);
const otherActions = toActions(contextMenuActionsGroups.filter(([group]) => group !== '0_install'), this.instantiationService);
if (themeActions.length) {
groups.push(themeActions);
}
groups.push([
this.instantiationService.createInstance(EnableGloballyAction),
@ -957,12 +969,12 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
this.instantiationService.createInstance(DisableForWorkspaceAction, runningExtensions)
]);
groups.push([
...(installActions[0] || []),
...(installActions.length ? installActions : []),
this.instantiationService.createInstance(InstallAnotherVersionAction),
this.instantiationService.createInstance(UninstallAction),
]);
otherActions.forEach(actions => groups.push(actions));
otherActionGroups.forEach(actions => groups.push(actions));
groups.forEach(group => group.forEach(extensionAction => {
if (extensionAction instanceof ExtensionAction) {
@ -1002,9 +1014,9 @@ export class ExtensionEditorManageExtensionAction extends ExtensionDropDownActio
update(): void { }
override run(): Promise<any> {
override async run(): Promise<any> {
const actionGroups: IAction[][] = [];
getContextMenuActions(this.extension, this.contextKeyService, this.instantiationService).forEach(actions => actionGroups.push(actions));
(await getContextMenuActions(this.extension, this.contextKeyService, this.instantiationService)).forEach(actions => actionGroups.push(actions));
actionGroups.forEach(group => group.forEach(extensionAction => {
if (extensionAction instanceof ExtensionAction) {
extensionAction.extension = this.extension;
@ -1503,30 +1515,27 @@ function getQuickPickEntries(themes: IWorkbenchTheme[], currentTheme: IWorkbench
return picks;
}
export class SetColorThemeAction extends ExtensionAction {
static readonly ID = 'workbench.extensions.action.setColorTheme';
static readonly TITLE = { value: localize('workbench.extensions.action.setColorTheme', "Set Color Theme"), original: 'Set Color Theme' };
private static readonly EnabledClass = `${ExtensionAction.LABEL_ACTION_CLASS} theme`;
private static readonly DisabledClass = `${SetColorThemeAction.EnabledClass} disabled`;
static async create(workbenchThemeService: IWorkbenchThemeService, instantiationService: IInstantiationService, extension: IExtension): Promise<SetColorThemeAction | undefined> {
const themes = await workbenchThemeService.getColorThemes();
if (themes.some(th => isThemeFromExtension(th, extension))) {
const action = instantiationService.createInstance(SetColorThemeAction, themes);
action.extension = extension;
return action;
}
return undefined;
}
private colorThemes: IWorkbenchColorTheme[] = [];
constructor(
private colorThemes: IWorkbenchColorTheme[],
@IExtensionService extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
) {
super(`extensions.colorTheme`, localize('color theme', "Set Color Theme"), SetColorThemeAction.DisabledClass, false);
super(SetColorThemeAction.ID, SetColorThemeAction.TITLE.value, SetColorThemeAction.DisabledClass, false);
this._register(Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidColorThemeChange)(() => this.update(), this));
workbenchThemeService.getColorThemes().then(colorThemes => {
this.colorThemes = colorThemes;
this.update();
});
this.update();
}
@ -1559,27 +1568,25 @@ export class SetColorThemeAction extends ExtensionAction {
export class SetFileIconThemeAction extends ExtensionAction {
static readonly ID = 'workbench.extensions.action.setFileIconTheme';
static readonly TITLE = { value: localize('workbench.extensions.action.setFileIconTheme', "Set File Icon Theme"), original: 'Set File Icon Theme' };
private static readonly EnabledClass = `${ExtensionAction.LABEL_ACTION_CLASS} theme`;
private static readonly DisabledClass = `${SetFileIconThemeAction.EnabledClass} disabled`;
static async create(workbenchThemeService: IWorkbenchThemeService, instantiationService: IInstantiationService, extension: IExtension): Promise<SetFileIconThemeAction | undefined> {
const themes = await workbenchThemeService.getFileIconThemes();
if (themes.some(th => isThemeFromExtension(th, extension))) {
const action = instantiationService.createInstance(SetFileIconThemeAction, themes);
action.extension = extension;
return action;
}
return undefined;
}
private fileIconThemes: IWorkbenchFileIconTheme[] = [];
constructor(
private fileIconThemes: IWorkbenchFileIconTheme[],
@IExtensionService extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super(`extensions.fileIconTheme`, localize('file icon theme', "Set File Icon Theme"), SetFileIconThemeAction.DisabledClass, false);
super(SetFileIconThemeAction.ID, SetFileIconThemeAction.TITLE.value, SetFileIconThemeAction.DisabledClass, false);
this._register(Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidFileIconThemeChange)(() => this.update(), this));
workbenchThemeService.getFileIconThemes().then(fileIconThemes => {
this.fileIconThemes = fileIconThemes;
this.update();
});
this.update();
}
@ -1611,30 +1618,26 @@ export class SetFileIconThemeAction extends ExtensionAction {
export class SetProductIconThemeAction extends ExtensionAction {
static readonly ID = 'workbench.extensions.action.setProductIconTheme';
static readonly TITLE = { value: localize('workbench.extensions.action.setProductIconTheme', "Set Product Icon Theme"), original: 'Set Product Icon Theme' };
private static readonly EnabledClass = `${ExtensionAction.LABEL_ACTION_CLASS} theme`;
private static readonly DisabledClass = `${SetProductIconThemeAction.EnabledClass} disabled`;
static async create(workbenchThemeService: IWorkbenchThemeService, instantiationService: IInstantiationService, extension: IExtension): Promise<SetProductIconThemeAction | undefined> {
const themes = await workbenchThemeService.getProductIconThemes();
if (themes.some(th => isThemeFromExtension(th, extension))) {
const action = instantiationService.createInstance(SetProductIconThemeAction, themes);
action.extension = extension;
return action;
}
return undefined;
}
private productIconThemes: IWorkbenchProductIconTheme[] = [];
constructor(
private productIconThemes: IWorkbenchProductIconTheme[],
@IExtensionService extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super(`extensions.productIconTheme`, localize('product icon theme', "Set Product Icon Theme"), SetProductIconThemeAction.DisabledClass, false);
super(SetProductIconThemeAction.ID, SetProductIconThemeAction.TITLE.value, SetProductIconThemeAction.DisabledClass, false);
this._register(Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidProductIconThemeChange)(() => this.update(), this));
this.enabled = true; // enabled by default
this.class = SetProductIconThemeAction.EnabledClass;
// this.update();
workbenchThemeService.getProductIconThemes().then(productIconThemes => {
this.productIconThemes = productIconThemes;
this.update();
});
this.update();
}
update(): void {

View file

@ -289,7 +289,7 @@ export class ExtensionsListView extends ViewPane {
if (manageExtensionAction.enabled) {
groups = await manageExtensionAction.getActionGroups(runningExtensions);
} else if (extension) {
groups = getContextMenuActions(extension, this.contextKeyService, this.instantiationService);
groups = await getContextMenuActions(extension, this.contextKeyService, this.instantiationService);
groups.forEach(group => group.forEach(extensionAction => {
if (extensionAction instanceof ExtensionAction) {
extensionAction.extension = extension;

View file

@ -226,30 +226,19 @@ class Extension implements IExtension {
return !!this.gallery?.hasReleaseVersion;
}
private getLocal(preRelease: boolean): ILocalExtension | undefined {
return this.local && !this.outdated && this.local.isPreReleaseVersion === preRelease ? this.local : undefined;
private getLocal(): ILocalExtension | undefined {
return this.local && !this.outdated ? this.local : undefined;
}
private async getGallery(preRelease: boolean, token: CancellationToken): Promise<IGalleryExtension | undefined> {
if (this.gallery) {
if (preRelease === this.gallery.properties.isPreReleaseVersion) {
return this.gallery;
}
return (await this.galleryService.getExtensions([this.gallery.identifier], preRelease, token))[0];
}
return undefined;
}
async getManifest(preRelease: boolean, token: CancellationToken): Promise<IExtensionManifest | null> {
const local = this.getLocal(preRelease);
async getManifest(token: CancellationToken): Promise<IExtensionManifest | null> {
const local = this.getLocal();
if (local) {
return local.manifest;
}
const gallery = await this.getGallery(preRelease, token);
if (gallery) {
if (gallery.assets.manifest) {
return this.galleryService.getManifest(gallery, token);
if (this.gallery) {
if (this.gallery.assets.manifest) {
return this.galleryService.getManifest(this.gallery, token);
}
this.logService.error(nls.localize('Manifest is not found', "Manifest is not found"), this.identifier.id);
return null;
@ -270,17 +259,16 @@ class Extension implements IExtension {
return this.type === ExtensionType.System;
}
async getReadme(preRelease: boolean, token: CancellationToken): Promise<string> {
const local = this.getLocal(preRelease);
async getReadme(token: CancellationToken): Promise<string> {
const local = this.getLocal();
if (local?.readmeUrl) {
const content = await this.fileService.readFile(local.readmeUrl);
return content.value.toString();
}
const gallery = await this.getGallery(preRelease, token);
if (gallery) {
if (gallery.assets.readme) {
return this.galleryService.getReadme(gallery, token);
if (this.gallery) {
if (this.gallery.assets.readme) {
return this.galleryService.getReadme(this.gallery, token);
}
this.telemetryService.publicLog('extensions:NotFoundReadMe', this.telemetryData);
}
@ -308,16 +296,15 @@ ${this.description}
return this.type === ExtensionType.System;
}
async getChangelog(preRelease: boolean, token: CancellationToken): Promise<string> {
const local = this.getLocal(preRelease);
async getChangelog(token: CancellationToken): Promise<string> {
const local = this.getLocal();
if (local?.changelogUrl) {
const content = await this.fileService.readFile(local.changelogUrl);
return content.value.toString();
}
const gallery = await this.getGallery(preRelease, token);
if (gallery?.assets.changelog) {
return this.galleryService.getChangelog(gallery, token);
if (this.gallery?.assets.changelog) {
return this.galleryService.getChangelog(this.gallery, token);
}
if (this.type === ExtensionType.System) {
@ -805,7 +792,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
const keywords = lookup[ext] || [];
// Get mode name
const languageId = this.languageService.getModeIdByFilepathOrFirstLine(URI.file(`.${ext}`));
const languageId = this.languageService.getLanguageIdByFilepathOrFirstLine(URI.file(`.${ext}`));
const languageName = languageId && this.languageService.getLanguageName(languageId);
const languageTag = languageName ? ` tag:"${languageName}"` : '';
@ -1018,27 +1005,41 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
.then(undefined, err => null);
}
private syncWithGallery(): Promise<void> {
const ids: string[] = [], names: string[] = [];
private async syncWithGallery(): Promise<void> {
const ids: string[] = [], preReleaseIds: string[] = [], names: string[] = [], preReleaseNames: string[] = [];
for (const installed of this.local) {
if (installed.type === ExtensionType.User) {
if (installed.identifier.uuid) {
ids.push(installed.identifier.uuid);
if (installed.local?.isPreReleaseVersion || installed.local?.preRelease) {
preReleaseIds.push(installed.identifier.uuid);
} else {
ids.push(installed.identifier.uuid);
}
} else {
names.push(installed.identifier.id);
if (installed.local?.isPreReleaseVersion || installed.local?.preRelease) {
preReleaseNames.push(installed.identifier.id);
} else {
names.push(installed.identifier.id);
}
}
}
}
const promises: Promise<IPager<IExtension>>[] = [];
if (ids.length) {
promises.push(this.queryGallery({ ids, pageSize: ids.length }, CancellationToken.None));
promises.push(this.queryGallery({ ids, pageSize: ids.length, includePreRelease: false }, CancellationToken.None));
}
if (preReleaseIds.length) {
promises.push(this.queryGallery({ ids: preReleaseIds, pageSize: preReleaseIds.length, includePreRelease: true }, CancellationToken.None));
}
if (names.length) {
promises.push(this.queryGallery({ names, pageSize: names.length }, CancellationToken.None));
promises.push(this.queryGallery({ names, pageSize: names.length, includePreRelease: false }, CancellationToken.None));
}
if (preReleaseNames.length) {
promises.push(this.queryGallery({ names: preReleaseNames, pageSize: names.length, includePreRelease: true }, CancellationToken.None));
}
return Promises.settled(promises).then(() => undefined);
await Promises.settled(promises);
}
private eventuallyAutoUpdateExtensions(): void {

View file

@ -68,11 +68,11 @@ export interface IExtension {
readonly extensionPack: string[];
readonly telemetryData: any;
readonly preview: boolean;
getManifest(preRelease: boolean, token: CancellationToken): Promise<IExtensionManifest | null>;
getManifest(token: CancellationToken): Promise<IExtensionManifest | null>;
hasReadme(): boolean;
getReadme(preRelease: boolean, token: CancellationToken): Promise<string>;
getReadme(token: CancellationToken): Promise<string>;
hasChangelog(): boolean;
getChangelog(preRelease: boolean, token: CancellationToken): Promise<string>;
getChangelog(token: CancellationToken): Promise<string>;
readonly server?: IExtensionManagementServer;
readonly local?: ILocalExtension;
gallery?: IGalleryExtension;
@ -181,3 +181,7 @@ export const LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID = 'workbench.exten
export const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
export const ExtensionsSortByContext = new RawContextKey<string>('extensionsSortByValue', '');
export const HasOutdatedExtensionsContext = new RawContextKey<boolean>('hasOutdatedExtensions', false);
// Context Menu Groups
export const THEME_ACTIONS_GROUP = '_theme_';
export const INSTALL_ACTIONS_GROUP = '0_install';

View file

@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { EditorInputCapabilities, IUntypedEditorInput } from 'vs/workbench/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { ExtensionEditorTab, IExtension, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { ExtensionEditorTab, IExtension } from 'vs/workbench/contrib/extensions/common/extensions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { join } from 'vs/base/common/path';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
@ -38,16 +38,8 @@ export class ExtensionsInput extends EditorInput {
});
}
constructor(
private _extension: IExtension,
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService
) {
constructor(private _extension: IExtension) {
super();
this._register(extensionsWorkbenchService.onChange(extension => {
if (extension && areSameExtensions(this._extension.identifier, extension.identifier)) {
this._extension = extension;
}
}));
}
get extension(): IExtension { return this._extension; }

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