mirror of
https://github.com/Microsoft/vscode
synced 2024-10-02 17:32:41 +00:00
Merge remote-tracking branch 'origin/main' into tyriar/137847
This commit is contained in:
commit
da7ab25150
2
.vscode/notebooks/api.github-issues
vendored
2
.vscode/notebooks/api.github-issues
vendored
|
@ -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,
|
||||
|
|
2
.vscode/notebooks/inbox.github-issues
vendored
2
.vscode/notebooks/inbox.github-issues
vendored
|
@ -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,
|
||||
|
|
2
.vscode/notebooks/my-work.github-issues
vendored
2
.vscode/notebooks/my-work.github-issues
vendored
|
@ -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,
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
111
build/yarn.lock
111
build/yarn.lock
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 () {',
|
||||
' // ',
|
||||
'',
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"license": "MIT",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "4.5"
|
||||
"typescript": "4.5.3"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[] = [];
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
10
package.json
10
package.json
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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==
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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' });
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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']));
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 [];
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)`);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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('~');
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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': {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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`);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'))
|
||||
},
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue