Merge remote-tracking branch 'origin/main' into tyriar/megan
This commit is contained in:
commit
982b28f42d
2
.devcontainer/cache/build-cache-image.sh
vendored
2
.devcontainer/cache/build-cache-image.sh
vendored
|
@ -8,7 +8,7 @@ set -e
|
|||
|
||||
SCRIPT_PATH="$(cd "$(dirname $0)" && pwd)"
|
||||
CONTAINER_IMAGE_REPOSITORY="$1"
|
||||
BRANCH="${2:-"master"}"
|
||||
BRANCH="${2:-"main"}"
|
||||
|
||||
if [ "${CONTAINER_IMAGE_REPOSITORY}" = "" ]; then
|
||||
echo "Container repository not specified!"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Code - OSS",
|
||||
|
||||
// Image contents: https://github.com/microsoft/vscode-dev-containers/blob/master/repository-containers/images/github.com/microsoft/vscode/.devcontainer/base.Dockerfile
|
||||
"image": "mcr.microsoft.com/vscode/devcontainers/repos/microsoft/vscode:branch-master",
|
||||
"image": "mcr.microsoft.com/vscode/devcontainers/repos/microsoft/vscode:branch-main",
|
||||
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/node/workspace/vscode,type=bind,consistency=cached",
|
||||
"workspaceFolder": "/home/node/workspace/vscode",
|
||||
|
|
|
@ -278,6 +278,7 @@
|
|||
"sinon",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/base/parts/*/{common,browser}/**",
|
||||
"**/vs/platform/*/{common,browser}/**",
|
||||
"**/vs/platform/*/test/{common,browser}/**"
|
||||
]
|
||||
|
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
|
@ -2,7 +2,7 @@
|
|||
* Read our Pull Request guidelines:
|
||||
https://github.com/microsoft/vscode/wiki/How-to-Contribute#pull-requests
|
||||
* Associate an issue with the Pull Request.
|
||||
* Ensure that the code is up-to-date with the `master` branch.
|
||||
* Ensure that the code is up-to-date with the `main` branch.
|
||||
* Include a description of the proposed changes and how to test them.
|
||||
-->
|
||||
|
||||
|
|
2
.github/workflows/build-chat.yml
vendored
2
.github/workflows/build-chat.yml
vendored
|
@ -7,7 +7,7 @@ on:
|
|||
types:
|
||||
- completed
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- release/*
|
||||
|
||||
jobs:
|
||||
|
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -3,11 +3,11 @@ name: CI
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- release/*
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- release/*
|
||||
|
||||
jobs:
|
||||
|
|
6
.github/workflows/devcontainer-cache.yml
vendored
6
.github/workflows/devcontainer-cache.yml
vendored
|
@ -2,9 +2,9 @@ name: VS Code Repo Dev Container Cache Image Generation
|
|||
|
||||
on:
|
||||
push:
|
||||
# Currently doing this for master, but could be done for PRs as well
|
||||
# Currently doing this for main, but could be done for PRs as well
|
||||
branches:
|
||||
- "master"
|
||||
- "main"
|
||||
|
||||
# Only updates to these files result in changes to installed packages, so skip otherwise
|
||||
paths:
|
||||
|
@ -35,6 +35,6 @@ jobs:
|
|||
az acr login --name $ACR_REGISTRY_NAME
|
||||
|
||||
GIT_BRANCH=$(echo "${{ github.ref }}" | grep -oP 'refs/(heads|tags)/\K(.+)')
|
||||
if [ "$GIT_BRANCH" == "" ]; then GIT_BRANCH=master; fi
|
||||
if [ "$GIT_BRANCH" == "" ]; then GIT_BRANCH=main; fi
|
||||
|
||||
.devcontainer/cache/build-cache-image.sh "${{ secrets.CONTAINER_IMAGE_REGISTRY }}/public/vscode/devcontainers/repos/microsoft/vscode" "${GIT_BRANCH}"
|
||||
|
|
2
.github/workflows/rich-navigation.yml
vendored
2
.github/workflows/rich-navigation.yml
vendored
|
@ -3,7 +3,7 @@ on:
|
|||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
jobs:
|
||||
richnav:
|
||||
|
|
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
|
@ -110,7 +110,8 @@
|
|||
// "${workspaceFolder}", // Uncomment for running out of sources.
|
||||
"${workspaceFolder}/extensions/vscode-api-tests/testWorkspace",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests",
|
||||
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/singlefolder-tests"
|
||||
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/singlefolder-tests",
|
||||
"--disable-extensions"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
|
|
2
.vscode/notebooks/inbox.github-issues
vendored
2
.vscode/notebooks/inbox.github-issues
vendored
|
@ -30,7 +30,7 @@
|
|||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "New issues or pull requests submitted by the community are initially triaged by an [automatic classification bot](https://github.com/microsoft/vscode-github-triage-actions/tree/master/classifier-deep). Issues that the bot does not correctly triage are then triaged by a team member. The team rotates the inbox tracker on a weekly basis.\n\nA [mirror](https://github.com/JacksonKearl/testissues/issues) of the VS Code issue stream is available with details about how the bot classifies issues, including feature-area classifications and confidence ratings. Per-category confidence thresholds and feature-area ownership data is maintained in [.github/classifier.json](https://github.com/microsoft/vscode/blob/master/.github/classifier.json). \n\n💡 The bot is being run through a GitHub action that runs every 30 minutes. Give the bot the opportunity to classify an issue before doing it manually.\n\n### Inbox Tracking\n\nThe inbox tracker is responsible for the [global inbox](https://github.com/microsoft/vscode/issues?utf8=%E2%9C%93&q=is%3Aopen+no%3Aassignee+-label%3Afeature-request+-label%3Atestplan-item+-label%3Aplan-item) containing all **open issues and pull requests** that\n- are neither **feature requests** nor **test plan items** nor **plan items** and\n- have **no owner assignment**.\n\nThe **inbox tracker** may perform any step described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) but its main responsibility is to route issues to the actual feature area owner.\n\nFeature area owners track the **feature area inbox** containing all **open issues and pull requests** that\n- are personally assigned to them and are not assigned to any milestone\n- are labeled with their feature area label and are not assigned to any milestone.\nThis secondary triage may involve any of the steps described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) and results in a fully triaged or closed issue.\n\nThe [github triage extension](https://github.com/microsoft/vscode-github-triage-extension) can be used to assist with triaging — it provides a \"Command Palette\"-style list of triaging actions like assignment, labeling, and triggers for various bot actions.",
|
||||
"value": "New issues or pull requests submitted by the community are initially triaged by an [automatic classification bot](https://github.com/microsoft/vscode-github-triage-actions/tree/master/classifier-deep). Issues that the bot does not correctly triage are then triaged by a team member. The team rotates the inbox tracker on a weekly basis.\n\nA [mirror](https://github.com/JacksonKearl/testissues/issues) of the VS Code issue stream is available with details about how the bot classifies issues, including feature-area classifications and confidence ratings. Per-category confidence thresholds and feature-area ownership data is maintained in [.github/classifier.json](https://github.com/microsoft/vscode/blob/main/.github/classifier.json). \n\n💡 The bot is being run through a GitHub action that runs every 30 minutes. Give the bot the opportunity to classify an issue before doing it manually.\n\n### Inbox Tracking\n\nThe inbox tracker is responsible for the [global inbox](https://github.com/microsoft/vscode/issues?utf8=%E2%9C%93&q=is%3Aopen+no%3Aassignee+-label%3Afeature-request+-label%3Atestplan-item+-label%3Aplan-item) containing all **open issues and pull requests** that\n- are neither **feature requests** nor **test plan items** nor **plan items** and\n- have **no owner assignment**.\n\nThe **inbox tracker** may perform any step described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) but its main responsibility is to route issues to the actual feature area owner.\n\nFeature area owners track the **feature area inbox** containing all **open issues and pull requests** that\n- are personally assigned to them and are not assigned to any milestone\n- are labeled with their feature area label and are not assigned to any milestone.\nThis secondary triage may involve any of the steps described in our [issue triaging documentation](https://github.com/microsoft/vscode/wiki/Issues-Triaging) and results in a fully triaged or closed issue.\n\nThe [github triage extension](https://github.com/microsoft/vscode-github-triage-extension) can be used to assist with triaging — it provides a \"Command Palette\"-style list of triaging actions like assignment, labeling, and triggers for various bot actions.",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
|
|
27
.vscode/notebooks/my-work.github-issues
vendored
27
.vscode/notebooks/my-work.github-issues
vendored
|
@ -8,7 +8,8 @@
|
|||
{
|
||||
"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\n\n// current milestone name\n$milestone=milestone:\"February 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\n\n// current milestone name\n$milestone=milestone:\"February 2021\"",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -19,7 +20,8 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos $milestone assignee:@me is:open"
|
||||
"value": "$repos $milestone assignee:@me is:open",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -36,7 +38,8 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open label:bug"
|
||||
"value": "$repos assignee:@me is:open label:bug",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -47,7 +50,8 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open label:debt OR $repos assignee:@me is:open label:engineering"
|
||||
"value": "$repos assignee:@me is:open label:debt OR $repos assignee:@me is:open label:engineering",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -58,7 +62,8 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open label:perf OR $repos assignee:@me is:open label:perf-startup OR $repos assignee:@me is:open label:perf-bloat OR $repos assignee:@me is:open label:freeze-slow-crash-leak"
|
||||
"value": "$repos assignee:@me is:open label:perf OR $repos assignee:@me is:open label:perf-startup OR $repos assignee:@me is:open label:perf-bloat OR $repos assignee:@me is:open label:freeze-slow-crash-leak",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -69,12 +74,14 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open label:feature-request milestone:Backlog sort:reactions-+1-desc"
|
||||
"value": "$repos assignee:@me is:open label:feature-request milestone:Backlog sort:reactions-+1-desc",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open milestone:\"Backlog Candidates\""
|
||||
"value": "$repos assignee:@me is:open milestone:\"Backlog Candidates\"",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -91,7 +98,8 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open type:issue -label:bug -label:\"needs more info\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream"
|
||||
"value": "$repos assignee:@me is:open type:issue -label:bug -label:\"needs more info\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream",
|
||||
"editable": true
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
@ -102,6 +110,7 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos assignee:@me is:open label:\"needs more info\""
|
||||
"value": "$repos assignee:@me is:open label:\"needs more info\"",
|
||||
"editable": true
|
||||
}
|
||||
]
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
## The Repository
|
||||
|
||||
This repository ("`Code - OSS`") is where we (Microsoft) develop the [Visual Studio Code](https://code.visualstudio.com) product. Not only do we work on code and issues here, we also publish our [roadmap](https://github.com/microsoft/vscode/wiki/Roadmap), [monthly iteration plans](https://github.com/microsoft/vscode/wiki/Iteration-Plans), and our [endgame plans](https://github.com/microsoft/vscode/wiki/Running-the-Endgame). This source code is available to everyone under the standard [MIT license](https://github.com/microsoft/vscode/blob/master/LICENSE.txt).
|
||||
This repository ("`Code - OSS`") is where we (Microsoft) develop the [Visual Studio Code](https://code.visualstudio.com) product. Not only do we work on code and issues here, we also publish our [roadmap](https://github.com/microsoft/vscode/wiki/Roadmap), [monthly iteration plans](https://github.com/microsoft/vscode/wiki/Iteration-Plans), and our [endgame plans](https://github.com/microsoft/vscode/wiki/Running-the-Endgame). This source code is available to everyone under the standard [MIT license](https://github.com/microsoft/vscode/blob/main/LICENSE.txt).
|
||||
|
||||
## Visual Studio Code
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ steps:
|
|||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
@ -387,7 +388,3 @@ steps:
|
|||
displayName: Upload configuration (for Bing settings search)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
continueOnError: true
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: "Component Detection"
|
||||
continueOnError: true
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
trigger:
|
||||
branches:
|
||||
include: ["master", "release/*"]
|
||||
include: ["main", "release/*"]
|
||||
pr:
|
||||
branches:
|
||||
include: ["master", "release/*"]
|
||||
include: ["main", "release/*"]
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
|
@ -31,8 +31,8 @@ steps:
|
|||
git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git"
|
||||
git fetch distro
|
||||
|
||||
# Push master branch into oss/master
|
||||
git push distro origin/master:refs/heads/oss/master
|
||||
# Push main branch into oss/main
|
||||
git push distro origin/main:refs/heads/oss/main
|
||||
|
||||
# Push every release branch into oss/release
|
||||
git for-each-ref --format="%(refname:short)" refs/remotes/origin/release/* | sed 's/^origin\/\(.*\)$/\0:refs\/heads\/oss\/\1/' | xargs git push distro
|
||||
|
|
|
@ -28,9 +28,9 @@ steps:
|
|||
git config user.name "VSCode"
|
||||
|
||||
git checkout origin/electron-11.x.y
|
||||
git merge origin/master
|
||||
git merge origin/main
|
||||
|
||||
# Push master branch into exploration branch
|
||||
# Push main branch into exploration branch
|
||||
git push origin HEAD:electron-11.x.y
|
||||
|
||||
displayName: Sync & Merge Exploration
|
||||
|
|
|
@ -69,6 +69,7 @@ steps:
|
|||
displayName: Extract node_modules cache
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
@ -132,7 +133,3 @@ steps:
|
|||
artifact: vscode-server-linux-alpine-web
|
||||
displayName: Publish web server archive
|
||||
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: "Component Detection"
|
||||
continueOnError: true
|
||||
|
|
|
@ -67,6 +67,7 @@ steps:
|
|||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['VSCODE_ARCH'], 'x64'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
@ -286,7 +287,3 @@ steps:
|
|||
artifactName: "snap-$(VSCODE_ARCH)"
|
||||
targetPath: .build/linux/snap-tarball
|
||||
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: "Component Detection"
|
||||
continueOnError: true
|
||||
|
|
|
@ -5,7 +5,7 @@ schedules:
|
|||
displayName: Mon-Fri at 7:00
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- main
|
||||
|
||||
parameters:
|
||||
- name: VSCODE_QUALITY
|
||||
|
|
|
@ -50,6 +50,7 @@ steps:
|
|||
displayName: Extract node_modules cache
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
@ -136,3 +137,7 @@ steps:
|
|||
targetPath: $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
artifactName: Compilation
|
||||
displayName: Publish compilation artifact
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: "Component Detection"
|
||||
continueOnError: true
|
||||
|
|
|
@ -61,7 +61,7 @@ steps:
|
|||
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
CHANNEL="G1C14HJ2F"
|
||||
|
||||
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:"
|
||||
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame champion, please open this link, examine changes and create a PR:"
|
||||
LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details."
|
||||
MESSAGE2="[@eamodio, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ function getNewFileHeader(tag: string) {
|
|||
`/*---------------------------------------------------------------------------------------------`,
|
||||
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
|
||||
` * Licensed under the MIT License.`,
|
||||
` * See https://github.com/microsoft/vscode/blob/master/LICENSE.txt for license information.`,
|
||||
` * See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.`,
|
||||
` *--------------------------------------------------------------------------------------------*/`,
|
||||
``,
|
||||
`/**`,
|
||||
|
|
|
@ -60,6 +60,7 @@ steps:
|
|||
displayName: Extract node_modules cache
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
|
|
@ -65,8 +65,10 @@ steps:
|
|||
condition: and(succeeded(), eq(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
displayName: Extract node_modules cache
|
||||
|
||||
- script: |
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { npx https://aka.ms/enablesecurefeed standAlone }
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
displayName: Switch to Terrapin packages
|
||||
|
@ -320,7 +322,3 @@ steps:
|
|||
artifact: vscode-server-win32-$(VSCODE_ARCH)-web
|
||||
displayName: Publish web server archive
|
||||
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: "Component Detection"
|
||||
continueOnError: true
|
||||
|
|
|
@ -49,7 +49,7 @@ let BUNDLED_FILE_HEADER = [
|
|||
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
||||
' * Version: ' + headerVersion,
|
||||
' * Released under the MIT license',
|
||||
' * https://github.com/microsoft/vscode/blob/master/LICENSE.txt',
|
||||
' * https://github.com/microsoft/vscode/blob/main/LICENSE.txt',
|
||||
' *-----------------------------------------------------------*/',
|
||||
''
|
||||
].join('\n');
|
||||
|
|
|
@ -52,13 +52,13 @@ const vscodeResources = [
|
|||
'out-build/bootstrap-amd.js',
|
||||
'out-build/bootstrap-node.js',
|
||||
'out-build/bootstrap-window.js',
|
||||
'out-build/paths.js',
|
||||
'out-build/vs/**/*.{svg,png,html,jpg}',
|
||||
'!out-build/vs/code/browser/**/*.html',
|
||||
'!out-build/vs/editor/standalone/**/*.svg',
|
||||
'out-build/vs/base/common/performance.js',
|
||||
'out-build/vs/base/node/languagePacks.js',
|
||||
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
|
||||
'out-build/vs/base/node/userDataPath.js',
|
||||
'out-build/vs/base/browser/ui/codicons/codicon/**',
|
||||
'out-build/vs/base/parts/sandbox/electron-browser/preload.js',
|
||||
'out-build/vs/workbench/browser/media/*-theme.css',
|
||||
|
@ -284,6 +284,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
|
|||
let result = all
|
||||
.pipe(util.skipDirectories())
|
||||
.pipe(util.fixWin32DirectoryPermissions())
|
||||
.pipe(filter(['**', '!**/.github/**'], { dot: true })) // https://github.com/microsoft/vscode/issues/116523
|
||||
.pipe(electron(_.extend({}, config, { platform, arch: arch === 'armhf' ? 'arm' : arch, ffmpegChromium: true })))
|
||||
.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version'], { dot: true }));
|
||||
|
||||
|
@ -526,7 +527,7 @@ gulp.task(task.define(
|
|||
|
||||
if (!shouldSetupSettingsSearch()) {
|
||||
const branch = process.env.BUILD_SOURCEBRANCH;
|
||||
console.log(`Only runs on master and release branches, not ${branch}`);
|
||||
console.log(`Only runs on main and release branches, not ${branch}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -552,21 +553,21 @@ gulp.task(task.define(
|
|||
|
||||
function shouldSetupSettingsSearch() {
|
||||
const branch = process.env.BUILD_SOURCEBRANCH;
|
||||
return branch && (/\/master$/.test(branch) || branch.indexOf('/release/') >= 0);
|
||||
return branch && (/\/main$/.test(branch) || branch.indexOf('/release/') >= 0);
|
||||
}
|
||||
|
||||
function getSettingsSearchBuildId(packageJson) {
|
||||
try {
|
||||
const branch = process.env.BUILD_SOURCEBRANCH;
|
||||
const branchId = branch.indexOf('/release/') >= 0 ? 0 :
|
||||
/\/master$/.test(branch) ? 1 :
|
||||
/\/main$/.test(branch) ? 1 :
|
||||
2; // Some unexpected branch
|
||||
|
||||
const out = cp.execSync(`git rev-list HEAD --count`);
|
||||
const count = parseInt(out.toString());
|
||||
|
||||
// <version number><commit count><branchId (avoid unlikely conflicts)>
|
||||
// 1.25.1, 1,234,567 commits, master = 1250112345671
|
||||
// 1.25.1, 1,234,567 commits, main = 1250112345671
|
||||
return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
|
||||
} catch (e) {
|
||||
throw new Error('Could not determine build number: ' + e.toString());
|
||||
|
|
|
@ -11,4 +11,4 @@ a good page describing the code editor's features is [here](https://code.visuals
|
|||
This npm module contains the core editor functionality, as it comes from the [vscode repository](https://github.com/microsoft/vscode).
|
||||
|
||||
## License
|
||||
[MIT](https://github.com/microsoft/vscode/blob/master/LICENSE.txt)
|
||||
[MIT](https://github.com/microsoft/vscode/blob/main/LICENSE.txt)
|
||||
|
|
|
@ -212,6 +212,11 @@
|
|||
"type": "number",
|
||||
"default": 0.3,
|
||||
"description": "%emmetPreferencesCssFuzzySearchMinScore%"
|
||||
},
|
||||
"output.reverseAttributes": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%emmetPreferencesOutputReverseAttributes%"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -430,8 +435,7 @@
|
|||
"deps": "yarn add vscode-emmet-helper"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.19.9",
|
||||
"emmet": "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
"@types/node": "^12.19.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emmetio/abbreviation": "^2.2.0",
|
||||
|
@ -439,7 +443,7 @@
|
|||
"@emmetio/html-matcher": "^0.3.3",
|
||||
"@emmetio/math-expression": "^1.0.4",
|
||||
"image-size": "^0.5.2",
|
||||
"vscode-emmet-helper": "2.2.4",
|
||||
"vscode-emmet-helper": "^2.3.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,5 +55,6 @@
|
|||
"emmetPreferencesCssOProperties": "Comma separated CSS properties that get the 'o' vendor prefix when used in Emmet abbreviation that starts with `-`. Set to empty string to always avoid the 'o' prefix.",
|
||||
"emmetPreferencesCssMsProperties": "Comma separated CSS properties that get the 'ms' vendor prefix when used in Emmet abbreviation that starts with `-`. Set to empty string to always avoid the 'ms' prefix.",
|
||||
"emmetPreferencesCssFuzzySearchMinScore": "The minimum score (from 0 to 1) that fuzzy-matched abbreviation should achieve. Lower values may produce many false-positive matches, higher values may reduce possible matches.",
|
||||
"emmetOptimizeStylesheetParsing": "When set to `false`, the whole file is parsed to determine if current position is valid for expanding Emmet abbreviations. When set to `true`, only the content around the current position in css/scss/less files is parsed."
|
||||
"emmetOptimizeStylesheetParsing": "When set to `false`, the whole file is parsed to determine if current position is valid for expanding Emmet abbreviations. When set to `true`, only the content around the current position in css/scss/less files is parsed.",
|
||||
"emmetPreferencesOutputReverseAttributes": "If `true`, reverses attribute merging directions when resolving snippets."
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@emmetio/abbreviation@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@emmetio/abbreviation/-/abbreviation-2.2.0.tgz#9f8dedbdb00e3136d6d37c6415375c82c0bb477f"
|
||||
integrity sha512-NPGVUmnr7cLj4i6MKS4c8NjuoIIJROrruJl/8nXsp2MdbDRHvtfq25foySvv/NbfqTQm+P9JzVLDD9JxGIpvkQ==
|
||||
"@emmetio/abbreviation@^2.2.0", "@emmetio/abbreviation@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@emmetio/abbreviation/-/abbreviation-2.2.1.tgz#d9458fe1f09fe042f019c48aa681165ba613a48d"
|
||||
integrity sha512-uUNwNgbH0JPlrdXhy8VQbNPLLG7abMvOaLVMblx22i68Rl9r+2N235ALgIYFUty1yXC9DkVw6xMbz/D4QVARcQ==
|
||||
dependencies:
|
||||
"@emmetio/scanner" "^1.0.0"
|
||||
|
||||
|
@ -54,15 +54,16 @@
|
|||
integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI=
|
||||
|
||||
"@types/node@^12.19.9":
|
||||
version "12.19.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.15.tgz#0de7e978fb43db62da369db18ea088a63673c182"
|
||||
integrity sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==
|
||||
version "12.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.0.tgz#692dfdecd6c97f5380c42dd50f19261f9f604deb"
|
||||
integrity sha512-0/41wHcurotvSOTHQUFkgL702c3pyWR1mToSrrX3pGPvGfpHTv3Ksx0M4UVuU5VJfjVb62Eyr1eKO1tWNUCg2Q==
|
||||
|
||||
"emmet@https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a":
|
||||
version "2.3.0"
|
||||
resolved "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
emmet@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/emmet/-/emmet-2.3.1.tgz#77614d949d1d01e5c248d08043a13a7f4d539e47"
|
||||
integrity sha512-u8h++9u3y9QWhn0imUXfQO+s80To5MGD97zd/00wGC39CfNGBPe//ZKepJz9I1LQ2FDRXHrn+e3JaN/53Y5z6A==
|
||||
dependencies:
|
||||
"@emmetio/abbreviation" "^2.2.0"
|
||||
"@emmetio/abbreviation" "^2.2.1"
|
||||
"@emmetio/css-abbreviation" "^2.1.2"
|
||||
|
||||
image-size@^0.5.2:
|
||||
|
@ -75,12 +76,12 @@ jsonc-parser@^2.3.0:
|
|||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342"
|
||||
integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
|
||||
|
||||
vscode-emmet-helper@2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.2.4.tgz#8ab86d2b7fe9e6270b4c77c9fd8d1eb8f3f4c401"
|
||||
integrity sha512-1N6bMzP1ZzkDGzamvsKxQ/lOmBc4+OQdj0dA2C9A5PSeYV9gh5xbJ061sm+VyFHOGZE+VyUQq5m/WFmFsLbKnA==
|
||||
vscode-emmet-helper@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.3.0.tgz#a98357ad5ac9c71d7c00396f22b7963b1a74cc5c"
|
||||
integrity sha512-QhU8+HlynMuUkqBYgA3wIDTSsUNkw8GWxLR214Hjvwr0lkFZa0CRqW/PzAI1CFREjSrTxJYQvkVnbfatZzKAuA==
|
||||
dependencies:
|
||||
emmet "https://github.com/rzhao271/emmet.git#1b2df677d8925ef5ea6da9df8845968403979a0a"
|
||||
emmet "^2.3.0"
|
||||
jsonc-parser "^2.3.0"
|
||||
vscode-languageserver-textdocument "^1.0.1"
|
||||
vscode-languageserver-types "^3.15.1"
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
"vscode:prepublish": "npm run compile"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": "2.6.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"uuid": "8.1.0",
|
||||
"vscode-extension-telemetry": "0.1.1",
|
||||
"vscode-nls": "^4.1.2"
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
const telemetryReporter = new TelemetryReporter(name, version, aiKey);
|
||||
|
||||
context.subscriptions.push(vscode.window.registerUriHandler(uriHandler));
|
||||
const loginService = new GitHubAuthenticationProvider(context);
|
||||
const loginService = new GitHubAuthenticationProvider(context, telemetryReporter);
|
||||
|
||||
await loginService.initialize(context);
|
||||
|
||||
|
@ -24,8 +24,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider('github', 'GitHub', {
|
||||
onDidChangeSessions: onDidChangeSessions.event,
|
||||
getAllSessions: () => Promise.resolve(loginService.sessions),
|
||||
getSessions: (scopes: string[]) => loginService.getSessions(scopes),
|
||||
getSessions: (scopes?: string[]) => loginService.getSessions(scopes),
|
||||
createSession: async (scopeList: string[]) => {
|
||||
try {
|
||||
/* __GDPR__
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Keychain } from './common/keychain';
|
|||
import { GitHubServer, NETWORK_ERROR } from './githubServer';
|
||||
import Logger from './common/logger';
|
||||
import { arrayEquals } from './common/utils';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
export const onDidChangeSessions = new vscode.EventEmitter<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent>();
|
||||
|
||||
|
@ -25,12 +26,13 @@ interface SessionData {
|
|||
|
||||
export class GitHubAuthenticationProvider {
|
||||
private _sessions: vscode.AuthenticationSession[] = [];
|
||||
private _githubServer = new GitHubServer();
|
||||
private _githubServer: GitHubServer;
|
||||
|
||||
private _keychain: Keychain;
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
constructor(context: vscode.ExtensionContext, telemetryReporter: TelemetryReporter) {
|
||||
this._keychain = new Keychain(context);
|
||||
this._githubServer = new GitHubServer(telemetryReporter);
|
||||
}
|
||||
|
||||
public async initialize(context: vscode.ExtensionContext): Promise<void> {
|
||||
|
@ -44,8 +46,10 @@ export class GitHubAuthenticationProvider {
|
|||
context.subscriptions.push(context.secrets.onDidChange(() => this.checkForUpdates()));
|
||||
}
|
||||
|
||||
async getSessions(scopes: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
return this._sessions.filter(session => arrayEquals(session.scopes, scopes));
|
||||
async getSessions(scopes?: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
return scopes
|
||||
? this._sessions.filter(session => arrayEquals(session.scopes, scopes))
|
||||
: this._sessions;
|
||||
}
|
||||
|
||||
private async verifySessions(): Promise<void> {
|
||||
|
@ -53,6 +57,7 @@ export class GitHubAuthenticationProvider {
|
|||
const verificationPromises = this._sessions.map(async session => {
|
||||
try {
|
||||
await this._githubServer.getUserInfo(session.accessToken);
|
||||
this._githubServer.checkIsEdu(session.accessToken);
|
||||
verifiedSessions.push(session);
|
||||
} catch (e) {
|
||||
// Remove sessions that return unauthorized response
|
||||
|
@ -161,6 +166,7 @@ export class GitHubAuthenticationProvider {
|
|||
public async createSession(scopes: string): Promise<vscode.AuthenticationSession> {
|
||||
const token = await this._githubServer.login(scopes);
|
||||
const session = await this.tokenToSession(token, scopes.split(' '));
|
||||
this._githubServer.checkIsEdu(token);
|
||||
await this.setToken(session);
|
||||
return session;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import fetch, { Response } from 'node-fetch';
|
|||
import { v4 as uuid } from 'uuid';
|
||||
import { PromiseAdapter, promiseFromEvent } from './common/utils';
|
||||
import Logger from './common/logger';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
|
@ -41,6 +42,8 @@ export class GitHubServer {
|
|||
private _pendingStates = new Map<string, string[]>();
|
||||
private _codeExchangePromises = new Map<string, Promise<string>>();
|
||||
|
||||
constructor(private readonly telemetryReporter: TelemetryReporter) { }
|
||||
|
||||
private isTestEnvironment(url: vscode.Uri): boolean {
|
||||
return url.authority === 'vscode-web-test-playground.azurewebsites.net' || url.authority.startsWith('localhost:');
|
||||
}
|
||||
|
@ -210,4 +213,36 @@ export class GitHubServer {
|
|||
throw new Error(result.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async checkIsEdu(token: string): Promise<void> {
|
||||
try {
|
||||
const result = await fetch('https://education.github.com/api/user', {
|
||||
headers: {
|
||||
Authorization: `token ${token}`,
|
||||
'faculty-check-preview': 'true',
|
||||
'User-Agent': 'Visual-Studio-Code'
|
||||
}
|
||||
});
|
||||
|
||||
if (result.ok) {
|
||||
const json: { student: boolean, faculty: boolean } = await result.json();
|
||||
|
||||
/* __GDPR__
|
||||
"session" : {
|
||||
"isEdu": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.sendTelemetryEvent('session', {
|
||||
isEdu: json.student
|
||||
? 'student'
|
||||
: json.faculty
|
||||
? 'faculty'
|
||||
: 'none'
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,10 +84,10 @@ mime-types@^2.1.12:
|
|||
dependencies:
|
||||
mime-db "1.44.0"
|
||||
|
||||
node-fetch@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
node-fetch@2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
semver@^5.3.0:
|
||||
version "5.7.1"
|
||||
|
|
|
@ -125,9 +125,9 @@ is-plain-object@^3.0.0:
|
|||
integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==
|
||||
|
||||
node-fetch@^2.3.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
once@^1.4.0:
|
||||
version "1.4.0"
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"buffer": "^5.6.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"randombytes": "github:rmacfarlane/randombytes#b28d4ecee46262801ea09f15fa1f1513a05c5971",
|
||||
"sha.js": "2.4.11",
|
||||
"stream": "0.0.2",
|
||||
|
|
|
@ -300,7 +300,11 @@ export class AzureActiveDirectoryService {
|
|||
return Promise.all(this._tokens.map(token => this.convertToSession(token)));
|
||||
}
|
||||
|
||||
async getSessions(scopes: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
async getSessions(scopes?: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
if (!scopes) {
|
||||
return this.sessions;
|
||||
}
|
||||
|
||||
const orderedScopes = scopes.sort().join(' ');
|
||||
const matchingTokens = this._tokens.filter(token => token.scope === orderedScopes);
|
||||
return Promise.all(matchingTokens.map(token => this.convertToSession(token)));
|
||||
|
|
|
@ -20,7 +20,6 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider('microsoft', 'Microsoft', {
|
||||
onDidChangeSessions: onDidChangeSessions.event,
|
||||
getAllSessions: () => Promise.resolve(loginService.sessions),
|
||||
getSessions: (scopes: string[]) => loginService.getSessions(scopes),
|
||||
createSession: async (scopes: string[]) => {
|
||||
try {
|
||||
|
|
|
@ -126,10 +126,10 @@ mime-types@^2.1.12:
|
|||
dependencies:
|
||||
mime-db "1.44.0"
|
||||
|
||||
node-fetch@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
node-fetch@2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
"randombytes@github:rmacfarlane/randombytes#b28d4ecee46262801ea09f15fa1f1513a05c5971":
|
||||
version "2.1.0"
|
||||
|
|
|
@ -303,7 +303,7 @@
|
|||
|
||||
"list.activeSelectionBackground": "#08286b",
|
||||
// "list.activeSelectionForeground": "",
|
||||
"list.focusBackground": "#08286b",
|
||||
"quickInput.list.focusBackground": "#08286b",
|
||||
"list.hoverBackground": "#061940",
|
||||
"list.inactiveSelectionBackground": "#152037",
|
||||
"list.dropBackground": "#041D52",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"list.highlightForeground": "#e3b583",
|
||||
"list.activeSelectionBackground": "#7c5021",
|
||||
"list.hoverBackground": "#7c502166",
|
||||
"list.focusBackground": "#7c5021AA",
|
||||
"quickInput.list.focusBackground": "#7c5021AA",
|
||||
"list.inactiveSelectionBackground": "#645342",
|
||||
"pickerGroup.foreground": "#e3b583",
|
||||
"pickerGroup.border": "#e3b583",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"colors": {
|
||||
"dropdown.background": "#525252",
|
||||
"list.activeSelectionBackground": "#707070",
|
||||
"list.focusBackground": "#707070",
|
||||
"quickInput.list.focusBackground": "#707070",
|
||||
"list.inactiveSelectionBackground": "#4e4e4e",
|
||||
"list.hoverBackground": "#444444",
|
||||
"list.highlightForeground": "#e58520",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"colors": {
|
||||
"dropdown.background": "#414339",
|
||||
"list.activeSelectionBackground": "#75715E",
|
||||
"list.focusBackground": "#414339",
|
||||
"quickInput.list.focusBackground": "#414339",
|
||||
"dropdown.listBackground": "#1e1f1c",
|
||||
"list.inactiveSelectionBackground": "#414339",
|
||||
"list.hoverBackground": "#3e3d32",
|
||||
|
|
|
@ -473,7 +473,7 @@
|
|||
"pickerGroup.foreground": "#A6B39B",
|
||||
"pickerGroup.border": "#749351",
|
||||
"list.activeSelectionForeground": "#6c6c6c",
|
||||
"list.focusBackground": "#CADEB9",
|
||||
"quickInput.list.focusBackground": "#CADEB9",
|
||||
"list.hoverBackground": "#e0e0e0",
|
||||
"list.activeSelectionBackground": "#c4d9b1",
|
||||
"list.inactiveSelectionBackground": "#d3dbcd",
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
"list.activeSelectionBackground": "#880000",
|
||||
"list.inactiveSelectionBackground": "#770000",
|
||||
"list.dropBackground": "#662222",
|
||||
"list.focusBackground": "#660000",
|
||||
"quickInput.list.focusBackground": "#660000",
|
||||
"list.highlightForeground": "#ff4444",
|
||||
"pickerGroup.foreground": "#cc9999",
|
||||
"pickerGroup.border": "#ff000033",
|
||||
|
|
|
@ -350,7 +350,7 @@
|
|||
|
||||
"list.activeSelectionBackground": "#005A6F",
|
||||
// "list.activeSelectionForeground": "",
|
||||
"list.focusBackground": "#005A6F",
|
||||
"quickInput.list.focusBackground": "#005A6F",
|
||||
"list.hoverBackground": "#004454AA",
|
||||
"list.inactiveSelectionBackground": "#00445488",
|
||||
"list.dropBackground": "#00445488",
|
||||
|
|
|
@ -350,7 +350,7 @@
|
|||
|
||||
"list.activeSelectionBackground": "#DFCA88",
|
||||
"list.activeSelectionForeground": "#6C6C6C",
|
||||
"list.focusBackground": "#DFCA8866",
|
||||
"quickInput.list.focusBackground": "#DFCA8866",
|
||||
"list.hoverBackground": "#DFCA8844",
|
||||
"list.inactiveSelectionBackground": "#D1CBB8",
|
||||
"list.highlightForeground": "#B58900",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"errorForeground": "#a92049",
|
||||
"input.background": "#001733",
|
||||
"dropdown.background": "#001733",
|
||||
"list.focusBackground": "#ffffff60",
|
||||
"quickInput.list.focusBackground": "#ffffff60",
|
||||
"list.activeSelectionBackground": "#ffffff60",
|
||||
"list.inactiveSelectionBackground": "#ffffff40",
|
||||
"list.hoverBackground": "#ffffff30",
|
||||
|
|
|
@ -116,6 +116,27 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"notebookProvider": [
|
||||
{
|
||||
"viewType": "notebookCoreTest",
|
||||
"displayName": "Notebook Core Test",
|
||||
"selector": [
|
||||
{
|
||||
"filenamePattern": "*.vsctestnb",
|
||||
"excludeFileNamePattern": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"viewType": "notebook.nbdtest",
|
||||
"displayName": "notebook.nbdtest",
|
||||
"selector": [
|
||||
{
|
||||
"filenamePattern": "**/*.nbdtest"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import * as utils from '../utils';
|
||||
|
||||
suite('Notebook Document', function () {
|
||||
|
||||
const contentProvider = new class implements vscode.NotebookContentProvider {
|
||||
async openNotebook(uri: vscode.Uri, _openContext: vscode.NotebookDocumentOpenContext): Promise<vscode.NotebookData> {
|
||||
return {
|
||||
cells: [{ cellKind: vscode.NotebookCellKind.Code, source: uri.toString(), language: 'javascript', metadata: {}, outputs: [] }],
|
||||
metadata: {}
|
||||
};
|
||||
}
|
||||
async resolveNotebook(_document: vscode.NotebookDocument, _webview: vscode.NotebookCommunication) {
|
||||
//
|
||||
}
|
||||
async saveNotebook(_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async saveNotebookAs(_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async backupNotebook(_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) {
|
||||
return { id: '', delete() { } };
|
||||
}
|
||||
};
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
// utils.assertNoRpc();
|
||||
await utils.revertAllDirty();
|
||||
await utils.closeAllEditors();
|
||||
utils.disposeAll(disposables);
|
||||
disposables.length = 0;
|
||||
|
||||
for (let doc of vscode.notebook.notebookDocuments) {
|
||||
assert.strictEqual(doc.isDirty, false, doc.uri.toString());
|
||||
}
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
disposables.push(vscode.notebook.registerNotebookContentProvider('notebook.nbdtest', contentProvider));
|
||||
});
|
||||
|
||||
test('cannot register sample provider multiple times', function () {
|
||||
assert.throws(() => {
|
||||
vscode.notebook.registerNotebookContentProvider('notebook.nbdtest', contentProvider);
|
||||
});
|
||||
});
|
||||
|
||||
test('cannot open unknown types', async function () {
|
||||
try {
|
||||
await vscode.notebook.openNotebookDocument(vscode.Uri.parse('some:///thing.notTypeKnown'));
|
||||
assert.ok(false);
|
||||
} catch {
|
||||
assert.ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('document basics', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const notebook = await vscode.notebook.openNotebookDocument(uri);
|
||||
|
||||
assert.strictEqual(notebook.uri.toString(), uri.toString());
|
||||
assert.strictEqual(notebook.isDirty, false);
|
||||
assert.strictEqual(notebook.isUntitled, false);
|
||||
assert.strictEqual(notebook.cells.length, 1);
|
||||
|
||||
assert.strictEqual(notebook.viewType, 'notebook.nbdtest');
|
||||
});
|
||||
|
||||
test('notebook open/close, notebook ready when cell-document open event is fired', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
let didHappen = false;
|
||||
const p = utils.asPromise(vscode.workspace.onDidOpenTextDocument).then(doc => {
|
||||
if (doc.uri.scheme !== 'vscode-notebook-cell') {
|
||||
return;
|
||||
}
|
||||
const notebook = vscode.notebook.notebookDocuments.find(notebook => {
|
||||
const cell = notebook.cells.find(cell => cell.document === doc);
|
||||
return Boolean(cell);
|
||||
});
|
||||
assert.ok(notebook, `notebook for cell ${doc.uri} NOT found`);
|
||||
didHappen = true;
|
||||
});
|
||||
|
||||
await vscode.notebook.openNotebookDocument(uri);
|
||||
await p;
|
||||
assert.strictEqual(didHappen, true);
|
||||
});
|
||||
|
||||
test('notebook open/close, all cell-documents are ready', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const p = utils.asPromise(vscode.notebook.onDidOpenNotebookDocument).then(notebook => {
|
||||
for (let cell of notebook.cells) {
|
||||
const doc = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === cell.uri.toString());
|
||||
assert.ok(doc);
|
||||
assert.strictEqual(doc.notebook === notebook, true);
|
||||
assert.strictEqual(doc === cell.document, true);
|
||||
assert.strictEqual(doc?.languageId, cell.language);
|
||||
assert.strictEqual(doc?.isDirty, false);
|
||||
assert.strictEqual(doc?.isClosed, false);
|
||||
}
|
||||
});
|
||||
|
||||
await vscode.notebook.openNotebookDocument(uri);
|
||||
await p;
|
||||
});
|
||||
|
||||
|
||||
test('workspace edit API (replaceCells)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const document = await vscode.notebook.openNotebookDocument(uri);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
// inserting two new cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// deleting cell 1 and 3
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, []);
|
||||
edit.replaceNotebookCells(document.uri, 2, 3, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_code');
|
||||
|
||||
// replacing all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_code'
|
||||
}]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 2);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new2_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new2_code');
|
||||
|
||||
// remove all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, document.cells.length, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 0);
|
||||
});
|
||||
|
||||
test('workspace edit API (replaceCells, event)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.notebook.openNotebookDocument(uri);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const event = utils.asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
|
||||
const data = await event;
|
||||
|
||||
// check document
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// check event data
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.changes.length, 1);
|
||||
assert.strictEqual(data.changes[0].deletedCount, 0);
|
||||
assert.strictEqual(data.changes[0].deletedItems.length, 0);
|
||||
assert.strictEqual(data.changes[0].items.length, 2);
|
||||
assert.strictEqual(data.changes[0].items[0], document.cells[0]);
|
||||
assert.strictEqual(data.changes[0].items[1], document.cells[1]);
|
||||
});
|
||||
});
|
|
@ -6,52 +6,13 @@
|
|||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { createRandomFile } from './utils';
|
||||
|
||||
export function timeoutAsync(n: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, n);
|
||||
});
|
||||
}
|
||||
|
||||
export function once<T>(event: vscode.Event<T>): vscode.Event<T> {
|
||||
return (listener: any, thisArgs = null, disposables?: any) => {
|
||||
// we need this, in case the event fires during the listener call
|
||||
let didFire = false;
|
||||
let result: vscode.Disposable;
|
||||
result = event(e => {
|
||||
if (didFire) {
|
||||
return;
|
||||
} else if (result) {
|
||||
result.dispose();
|
||||
} else {
|
||||
didFire = true;
|
||||
}
|
||||
|
||||
return listener.call(thisArgs, e);
|
||||
}, null, disposables);
|
||||
|
||||
if (didFire) {
|
||||
result.dispose();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
async function getEventOncePromise<T>(event: vscode.Event<T>): Promise<T> {
|
||||
return new Promise<T>((resolve, _reject) => {
|
||||
once(event)((result: T) => resolve(result));
|
||||
});
|
||||
}
|
||||
import { createRandomFile, asPromise, disposeAll, closeAllEditors, revertAllDirty } from '../utils';
|
||||
|
||||
// Since `workbench.action.splitEditor` command does await properly
|
||||
// Notebook editor/document events are not guaranteed to be sent to the ext host when promise resolves
|
||||
// The workaround here is waiting for the first visible notebook editor change event.
|
||||
async function splitEditor() {
|
||||
const once = getEventOncePromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
const once = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await vscode.commands.executeCommand('workbench.action.splitEditor');
|
||||
await once;
|
||||
}
|
||||
|
@ -100,7 +61,7 @@ async function updateNotebookMetadata(uri: vscode.Uri, newMetadata: vscode.Noteb
|
|||
}
|
||||
|
||||
async function withEvent<T>(event: vscode.Event<T>, callback: (e: Promise<T>) => Promise<void>) {
|
||||
const e = getEventOncePromise<T>(event);
|
||||
const e = asPromise<T>(event);
|
||||
await callback(e);
|
||||
}
|
||||
|
||||
|
@ -112,7 +73,146 @@ function assertInitalState() {
|
|||
// assert.strictEqual(vscode.notebook.visibleNotebookEditors.length, 0);
|
||||
}
|
||||
|
||||
suite('Notebook API tests', () => {
|
||||
suite('Notebook API tests', function () {
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
await revertAllDirty();
|
||||
await closeAllEditors();
|
||||
|
||||
disposeAll(disposables);
|
||||
disposables.length = 0;
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
disposables.push(vscode.notebook.registerNotebookContentProvider('notebookCoreTest', {
|
||||
openNotebook: async (_resource: vscode.Uri): Promise<vscode.NotebookData> => {
|
||||
if (/.*empty\-.*\.vsctestnb$/.test(_resource.path)) {
|
||||
return {
|
||||
metadata: {},
|
||||
cells: []
|
||||
};
|
||||
}
|
||||
|
||||
const dto: vscode.NotebookData = {
|
||||
metadata: {
|
||||
custom: { testMetadata: false }
|
||||
},
|
||||
cells: [
|
||||
{
|
||||
source: 'test',
|
||||
language: 'typescript',
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
outputs: [],
|
||||
metadata: {
|
||||
custom: { testCellMetadata: 123 }
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
return dto;
|
||||
},
|
||||
resolveNotebook: async (_document: vscode.NotebookDocument) => {
|
||||
return;
|
||||
},
|
||||
saveNotebook: async (_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
|
||||
return;
|
||||
},
|
||||
saveNotebookAs: async (_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
|
||||
return;
|
||||
},
|
||||
backupNotebook: async (_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) => {
|
||||
return {
|
||||
id: '1',
|
||||
delete: () => { }
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
const kernel: vscode.NotebookKernel = {
|
||||
id: 'mainKernel',
|
||||
label: 'Notebook Test Kernel',
|
||||
isPreferred: true,
|
||||
supportedLanguages: ['typescript'],
|
||||
executeAllCells: async (_document: vscode.NotebookDocument) => {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
||||
edit.replaceNotebookCellOutput(_document.uri, 0, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined)
|
||||
])]);
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelAllCellsExecution: async (_document: vscode.NotebookDocument) => { },
|
||||
executeCell: async (document: vscode.NotebookDocument, cell: vscode.NotebookCell | undefined) => {
|
||||
if (!cell) {
|
||||
cell = document.cells[0];
|
||||
}
|
||||
|
||||
if (document.uri.path.endsWith('customRenderer.vsctestnb')) {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/custom', ['test'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
}
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
// const previousOutputs = cell.outputs;
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { }
|
||||
};
|
||||
|
||||
const kernel2: vscode.NotebookKernel = {
|
||||
id: 'secondaryKernel',
|
||||
label: 'Notebook Secondary Test Kernel',
|
||||
isPreferred: false,
|
||||
supportedLanguages: ['typescript'],
|
||||
executeAllCells: async (_document: vscode.NotebookDocument) => {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellOutput(_document.uri, 0, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelAllCellsExecution: async (_document: vscode.NotebookDocument) => { },
|
||||
executeCell: async (document: vscode.NotebookDocument, cell: vscode.NotebookCell | undefined) => {
|
||||
if (!cell) {
|
||||
cell = document.cells[0];
|
||||
}
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
||||
if (document.uri.path.endsWith('customRenderer.vsctestnb')) {
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/custom', ['test 2'], undefined)
|
||||
])]);
|
||||
} else {
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined)
|
||||
])]);
|
||||
}
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { }
|
||||
};
|
||||
|
||||
disposables.push(vscode.notebook.registerNotebookKernelProvider({ filenamePattern: '*.vsctestnb' }, {
|
||||
provideKernels: async () => {
|
||||
return [kernel, kernel2];
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
// test.only('crash', async function () {
|
||||
// for (let i = 0; i < 200; i++) {
|
||||
// let resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
|
||||
|
@ -141,60 +241,20 @@ suite('Notebook API tests', () => {
|
|||
test('document open/close event', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const firstDocumentOpen = getEventOncePromise(vscode.notebook.onDidOpenNotebookDocument);
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
const firstDocumentOpen = asPromise(vscode.notebook.onDidOpenNotebookDocument);
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await firstDocumentOpen;
|
||||
|
||||
const firstDocumentClose = getEventOncePromise(vscode.notebook.onDidCloseNotebookDocument);
|
||||
const firstDocumentClose = asPromise(vscode.notebook.onDidCloseNotebookDocument);
|
||||
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
await firstDocumentClose;
|
||||
});
|
||||
|
||||
test('notebook open/close, all cell-documents are ready', async function () {
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
|
||||
const p = getEventOncePromise(vscode.notebook.onDidOpenNotebookDocument).then(notebook => {
|
||||
for (let cell of notebook.cells) {
|
||||
const doc = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === cell.uri.toString());
|
||||
assert.ok(doc);
|
||||
assert.strictEqual(doc === cell.document, true);
|
||||
assert.strictEqual(doc?.languageId, cell.language);
|
||||
assert.strictEqual(doc?.isDirty, false);
|
||||
assert.strictEqual(doc?.isClosed, false);
|
||||
}
|
||||
});
|
||||
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await p;
|
||||
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
});
|
||||
|
||||
test('notebook open/close, notebook ready when cell-document open event is fired', async function () {
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
let didHappen = false;
|
||||
const p = getEventOncePromise(vscode.workspace.onDidOpenTextDocument).then(doc => {
|
||||
if (doc.uri.scheme !== 'vscode-notebook-cell') {
|
||||
return;
|
||||
}
|
||||
const notebook = vscode.notebook.notebookDocuments.find(notebook => {
|
||||
const cell = notebook.cells.find(cell => cell.document === doc);
|
||||
return Boolean(cell);
|
||||
});
|
||||
assert.ok(notebook, `notebook for cell ${doc.uri} NOT found`);
|
||||
didHappen = true;
|
||||
});
|
||||
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await p;
|
||||
assert.strictEqual(didHappen, true);
|
||||
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
});
|
||||
|
||||
test('shared document in notebook editors', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
let counter = 0;
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
disposables.push(vscode.notebook.onDidOpenNotebookDocument(() => {
|
||||
|
@ -217,12 +277,12 @@ suite('Notebook API tests', () => {
|
|||
test('editor open/close event', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const firstEditorOpen = getEventOncePromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
const firstEditorOpen = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await firstEditorOpen;
|
||||
|
||||
const firstEditorClose = getEventOncePromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
const firstEditorClose = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
await firstEditorClose;
|
||||
});
|
||||
|
@ -230,7 +290,7 @@ suite('Notebook API tests', () => {
|
|||
test('editor open/close event 2', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
let count = 0;
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
disposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
|
||||
|
@ -250,10 +310,10 @@ suite('Notebook API tests', () => {
|
|||
test('editor editing event 2', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
const cellChangeEventRet = await cellsChangeEvent;
|
||||
assert.strictEqual(cellChangeEventRet.document, vscode.window.activeNotebookEditor?.document);
|
||||
|
@ -269,7 +329,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
const secondCell = vscode.window.activeNotebookEditor!.document.cells[1];
|
||||
|
||||
const moveCellEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const moveCellEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.moveUp');
|
||||
const moveCellEventRet = await moveCellEvent;
|
||||
assert.deepStrictEqual(moveCellEventRet, {
|
||||
|
@ -290,7 +350,7 @@ suite('Notebook API tests', () => {
|
|||
]
|
||||
});
|
||||
|
||||
const cellOutputChange = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const cellOutputChange = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
const cellOutputsAddedRet = await cellOutputChange;
|
||||
assert.deepStrictEqual(cellOutputsAddedRet, {
|
||||
|
@ -299,7 +359,7 @@ suite('Notebook API tests', () => {
|
|||
});
|
||||
assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 1);
|
||||
|
||||
const cellOutputClear = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const cellOutputClear = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
||||
const cellOutputsCleardRet = await cellOutputClear;
|
||||
assert.deepStrictEqual(cellOutputsCleardRet, {
|
||||
|
@ -323,7 +383,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('editor move cell event', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
|
@ -331,7 +391,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
const activeCell = vscode.window.activeNotebookEditor!.selection;
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0);
|
||||
const moveChange = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells);
|
||||
const moveChange = asPromise(vscode.notebook.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||
const ret = await moveChange;
|
||||
assert.deepStrictEqual(ret, {
|
||||
|
@ -365,7 +425,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('notebook editor active/visible', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
const firstEditor = vscode.window.activeNotebookEditor;
|
||||
assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
|
||||
|
@ -377,7 +437,7 @@ suite('Notebook API tests', () => {
|
|||
assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
|
||||
|
||||
const untitledEditorChange = getEventOncePromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const untitledEditorChange = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
|
||||
await untitledEditorChange;
|
||||
assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
|
||||
|
@ -386,7 +446,7 @@ suite('Notebook API tests', () => {
|
|||
assert.notStrictEqual(secondEditor, vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
|
||||
|
||||
const activeEditorClose = getEventOncePromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const activeEditorClose = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
await activeEditorClose;
|
||||
assert.strictEqual(secondEditor, vscode.window.activeNotebookEditor);
|
||||
|
@ -399,12 +459,12 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('notebook active editor change', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const firstEditorOpen = getEventOncePromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
const firstEditorOpen = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await firstEditorOpen;
|
||||
|
||||
const firstEditorDeactivate = getEventOncePromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const firstEditorDeactivate = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.splitEditor');
|
||||
await firstEditorDeactivate;
|
||||
|
||||
|
@ -413,10 +473,10 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('edit API (replaceCells)', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.NotebookCellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: undefined }]);
|
||||
});
|
||||
|
@ -434,7 +494,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('edit API (replaceOutput, USE NotebookCellOutput-type)', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
|
@ -463,7 +523,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('edit API (replaceOutput)', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
|
@ -485,10 +545,10 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('edit API (replaceOutput, event)', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const outputChangeEvent = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const outputChangeEvent = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCellOutput(0, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('foo', 'bar')
|
||||
|
@ -511,7 +571,7 @@ suite('Notebook API tests', () => {
|
|||
test('edit API (replaceMetadata)', async function () {
|
||||
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
|
@ -530,10 +590,10 @@ suite('Notebook API tests', () => {
|
|||
test('edit API (replaceMetadata, event)', async function () {
|
||||
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const event = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
const event = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCellMetadata(0, { inputCollapsed: true, executionOrder: 17 });
|
||||
|
@ -548,141 +608,13 @@ suite('Notebook API tests', () => {
|
|||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
|
||||
test('workspace edit API (replaceCells)', async function () {
|
||||
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const { document } = vscode.window.activeNotebookEditor!;
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
// inserting two new cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// deleting cell 1 and 3
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, []);
|
||||
edit.replaceNotebookCells(document.uri, 2, 3, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_code');
|
||||
|
||||
// replacing all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_code'
|
||||
}]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 2);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new2_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new2_code');
|
||||
|
||||
// remove all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, document.cells.length, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 0);
|
||||
|
||||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
|
||||
test('workspace edit API (replaceCells, event)', async function () {
|
||||
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const { document } = vscode.window.activeNotebookEditor!;
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const event = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
|
||||
const data = await event;
|
||||
|
||||
// check document
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// check event data
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.changes.length, 1);
|
||||
assert.strictEqual(data.changes[0].deletedCount, 0);
|
||||
assert.strictEqual(data.changes[0].deletedItems.length, 0);
|
||||
assert.strictEqual(data.changes[0].items.length, 2);
|
||||
assert.strictEqual(data.changes[0].items[0], document.cells[0]);
|
||||
assert.strictEqual(data.changes[0].items[1], document.cells[1]);
|
||||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
|
||||
test('edit API batch edits', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.NotebookCellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: undefined }]);
|
||||
|
@ -697,11 +629,11 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('edit API batch edits undo/redo', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.NotebookCellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: undefined }]);
|
||||
|
@ -724,7 +656,7 @@ suite('Notebook API tests', () => {
|
|||
|
||||
test('initialzation should not emit cell change events.', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
|
||||
let count = 0;
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
@ -739,12 +671,13 @@ suite('Notebook API tests', () => {
|
|||
|
||||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
// suite('notebook workflow', () => {
|
||||
|
||||
suite('notebook workflow', () => {
|
||||
test('notebook open', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test');
|
||||
|
@ -766,7 +699,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('notebook cell actions', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test');
|
||||
|
@ -840,7 +773,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('notebook join cells', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test');
|
||||
|
@ -852,7 +785,7 @@ suite('notebook workflow', () => {
|
|||
edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
|
||||
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.joinAbove');
|
||||
await cellsChangeEvent;
|
||||
|
||||
|
@ -864,7 +797,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('move cells will not recreate cells in ExtHost', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
|
@ -884,7 +817,7 @@ suite('notebook workflow', () => {
|
|||
});
|
||||
|
||||
// test.only('document metadata is respected', async function () {
|
||||
// const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
// const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
|
@ -909,7 +842,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('cell runnable metadata is respected', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
|
@ -918,14 +851,14 @@ suite('notebook workflow', () => {
|
|||
const cell = editor.document.cells[0];
|
||||
assert.strictEqual(cell.outputs.length, 0);
|
||||
|
||||
let metadataChangeEvent = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
let metadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
await updateCellMetadata(resource, cell, { ...cell.metadata, runnable: false });
|
||||
await metadataChangeEvent;
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
|
||||
|
||||
metadataChangeEvent = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
metadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
await updateCellMetadata(resource, cell, { ...cell.metadata, runnable: true });
|
||||
await metadataChangeEvent;
|
||||
|
||||
|
@ -938,7 +871,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('document runnable metadata is respected', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
|
@ -973,7 +906,7 @@ suite('notebook workflow', () => {
|
|||
// TODO@rebornix this is wrong, `await vscode.commands.executeCommand('notebook.execute');` doesn't wait until the workspace edit is applied
|
||||
test.skip('cell execute command takes arguments', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
|
@ -988,7 +921,7 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('cell execute command takes arguments 2', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
|
@ -1011,7 +944,7 @@ suite('notebook workflow', () => {
|
|||
assert.strictEqual(cell.outputs.length, 0, 'should clear');
|
||||
});
|
||||
|
||||
const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb');
|
||||
const secondResource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
|
||||
|
||||
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
|
||||
|
@ -1029,13 +962,13 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('document execute command takes arguments', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
const cell = editor.document.cells[0];
|
||||
|
||||
const metadataChangeEvent = getEventOncePromise<vscode.NotebookDocumentMetadataChangeEvent>(vscode.notebook.onDidChangeNotebookDocumentMetadata);
|
||||
const metadataChangeEvent = asPromise<vscode.NotebookDocumentMetadataChangeEvent>(vscode.notebook.onDidChangeNotebookDocumentMetadata);
|
||||
updateNotebookMetadata(editor.document.uri, { ...editor.document.metadata, runnable: true });
|
||||
await metadataChangeEvent;
|
||||
assert.strictEqual(editor.document.metadata.runnable, true);
|
||||
|
@ -1046,12 +979,12 @@ suite('notebook workflow', () => {
|
|||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
});
|
||||
|
||||
const clearChangeEvent = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const clearChangeEvent = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
||||
await clearChangeEvent;
|
||||
assert.strictEqual(cell.outputs.length, 0, 'should clear');
|
||||
|
||||
const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb');
|
||||
const secondResource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
|
||||
|
||||
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
|
||||
|
@ -1069,13 +1002,13 @@ suite('notebook workflow', () => {
|
|||
|
||||
test('cell execute and select kernel', async () => {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
const cell = editor.document.cells[0];
|
||||
|
||||
const metadataChangeEvent = getEventOncePromise<vscode.NotebookDocumentMetadataChangeEvent>(vscode.notebook.onDidChangeNotebookDocumentMetadata);
|
||||
const metadataChangeEvent = asPromise<vscode.NotebookDocumentMetadataChangeEvent>(vscode.notebook.onDidChangeNotebookDocumentMetadata);
|
||||
updateNotebookMetadata(editor.document.uri, { ...editor.document.metadata, runnable: true });
|
||||
await metadataChangeEvent;
|
||||
|
||||
|
@ -1087,7 +1020,7 @@ suite('notebook workflow', () => {
|
|||
'my output'
|
||||
]);
|
||||
|
||||
await vscode.commands.executeCommand('notebook.selectKernel', { extension: 'vscode.vscode-notebook-tests', id: 'secondaryKernel' });
|
||||
await vscode.commands.executeCommand('notebook.selectKernel', { extension: 'vscode.vscode-api-tests', id: 'secondaryKernel' });
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
assert.strictEqual(cell.outputs[0].outputs.length, 1);
|
||||
|
@ -1099,12 +1032,12 @@ suite('notebook workflow', () => {
|
|||
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
suite('notebook dirty state', () => {
|
||||
// suite('notebook dirty state', () => {
|
||||
test('notebook open', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test');
|
||||
|
@ -1133,12 +1066,12 @@ suite('notebook dirty state', () => {
|
|||
|
||||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
suite('notebook undo redo', () => {
|
||||
// suite('notebook undo redo', () => {
|
||||
test('notebook open', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test');
|
||||
|
@ -1181,7 +1114,7 @@ suite('notebook undo redo', () => {
|
|||
|
||||
// test.skip('execute and then undo redo', async function () {
|
||||
// assertInitalState();
|
||||
// const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
// const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
// const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
|
@ -1242,11 +1175,11 @@ suite('notebook undo redo', () => {
|
|||
// await saveFileAndCloseAll(resource);
|
||||
// });
|
||||
|
||||
});
|
||||
// });
|
||||
|
||||
suite('notebook working copy', () => {
|
||||
// suite('notebook working copy', () => {
|
||||
// test('notebook revert on close', async function () {
|
||||
// const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
// const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
// await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), '');
|
||||
|
@ -1267,7 +1200,7 @@ suite('notebook working copy', () => {
|
|||
// });
|
||||
|
||||
// test('notebook revert', async function () {
|
||||
// const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
// const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
// await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), '');
|
||||
|
@ -1288,7 +1221,7 @@ suite('notebook working copy', () => {
|
|||
|
||||
test('multiple tabs: dirty + clean', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), '');
|
||||
|
@ -1298,7 +1231,7 @@ suite('notebook working copy', () => {
|
|||
edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
|
||||
const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb');
|
||||
const secondResource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
|
||||
|
@ -1314,7 +1247,7 @@ suite('notebook working copy', () => {
|
|||
|
||||
test('multiple tabs: two dirty tabs and switching', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), '');
|
||||
|
@ -1324,7 +1257,7 @@ suite('notebook working copy', () => {
|
|||
edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
|
||||
const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb');
|
||||
const secondResource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), '');
|
||||
|
@ -1353,7 +1286,7 @@ suite('notebook working copy', () => {
|
|||
test('multiple tabs: different editors with same document', async function () {
|
||||
assertInitalState();
|
||||
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
const firstNotebookEditor = vscode.window.activeNotebookEditor;
|
||||
assert.strictEqual(firstNotebookEditor !== undefined, true, 'notebook first');
|
||||
|
@ -1375,12 +1308,12 @@ suite('notebook working copy', () => {
|
|||
// await vscode.commands.executeCommand('workbench.action.files.saveAll');
|
||||
// await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
suite('metadata', () => {
|
||||
// suite('metadata', () => {
|
||||
test('custom metadata should be supported', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
|
||||
|
@ -1394,7 +1327,7 @@ suite('metadata', () => {
|
|||
// TODO@rebornix skip as it crashes the process all the time
|
||||
test.skip('custom metadata should be supported 2', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
|
||||
|
@ -1409,9 +1342,9 @@ suite('metadata', () => {
|
|||
|
||||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
suite('regression', () => {
|
||||
// suite('regression', () => {
|
||||
// test('microsoft/vscode-github-issue-notebooks#26. Insert template cell in the new empty document', async function () {
|
||||
// assertInitalState();
|
||||
// await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { "viewType": "notebookCoreTest" });
|
||||
|
@ -1423,7 +1356,7 @@ suite('regression', () => {
|
|||
|
||||
test('#106657. Opening a notebook from markers view is broken ', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const document = vscode.window.activeNotebookEditor?.document!;
|
||||
|
@ -1441,7 +1374,7 @@ suite('regression', () => {
|
|||
|
||||
test.skip('Cannot open notebook from cell-uri with vscode.open-command', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
const document = vscode.window.activeNotebookEditor?.document!;
|
||||
|
@ -1459,7 +1392,7 @@ suite('regression', () => {
|
|||
|
||||
test('#97830, #97764. Support switch to other editor types', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'empty', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
@ -1469,12 +1402,9 @@ suite('regression', () => {
|
|||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'var abc = 0;');
|
||||
|
||||
// todo@jrieken enforce a kernel (how) and test that its language is picked
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.language, 'typescript');
|
||||
|
||||
// no kernel -> no default language
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.kernel, undefined);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.language, 'plaintext');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.selection?.language, 'typescript');
|
||||
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
|
||||
assert.strictEqual(vscode.window.activeTextEditor?.document.uri.path, resource.path);
|
||||
|
@ -1485,7 +1415,7 @@ suite('regression', () => {
|
|||
// open text editor, pin, and then open a notebook
|
||||
test('#96105 - dirty editors', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'empty', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.insert(resource, new vscode.Position(0, 0), 'var abc = 0;');
|
||||
|
@ -1509,7 +1439,7 @@ suite('regression', () => {
|
|||
|
||||
test('#102423 - copy/paste shares the same text buffer', async function () {
|
||||
assertInitalState();
|
||||
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
let activeCell = vscode.window.activeNotebookEditor!.selection;
|
||||
|
@ -1530,16 +1460,16 @@ suite('regression', () => {
|
|||
|
||||
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
});
|
||||
});
|
||||
// });
|
||||
|
||||
suite('webview', () => {
|
||||
// suite('webview', () => {
|
||||
// for web, `asWebUri` gets `https`?
|
||||
// test('asWebviewUri', async function () {
|
||||
// if (vscode.env.uiKind === vscode.UIKind.Web) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
|
||||
// const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
// const uri = vscode.window.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
|
|
@ -150,6 +150,13 @@ suite('vscode API - window', () => {
|
|||
});
|
||||
|
||||
test('active editor not always correct... #49125', async function () {
|
||||
|
||||
if (!window.state.focused) {
|
||||
// no focus!
|
||||
this.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env['BUILD_SOURCEVERSION']) {
|
||||
this.skip();
|
||||
return;
|
||||
|
|
|
@ -17,7 +17,7 @@ vscode.workspace.registerFileSystemProvider(testFs.scheme, testFs, { isCaseSensi
|
|||
export async function createRandomFile(contents = '', dir: vscode.Uri | undefined = undefined, ext = ''): Promise<vscode.Uri> {
|
||||
let fakeFile: vscode.Uri;
|
||||
if (dir) {
|
||||
assert.equal(dir.scheme, testFs.scheme);
|
||||
assert.strictEqual(dir.scheme, testFs.scheme);
|
||||
fakeFile = dir.with({ path: dir.path + '/' + rndName() + ext });
|
||||
} else {
|
||||
fakeFile = vscode.Uri.parse(`${testFs.scheme}:/${rndName() + ext}`);
|
||||
|
@ -48,6 +48,10 @@ export function closeAllEditors(): Thenable<any> {
|
|||
return vscode.commands.executeCommand('workbench.action.closeAllEditors');
|
||||
}
|
||||
|
||||
export function saveAllEditors(): Thenable<any> {
|
||||
return vscode.commands.executeCommand('workbench.action.files.saveAll');
|
||||
}
|
||||
|
||||
export async function revertAllDirty(): Promise<void> {
|
||||
return vscode.commands.executeCommand('_workbench.revertAllDirty');
|
||||
}
|
||||
|
@ -117,3 +121,19 @@ export function assertNoRpcFromEntry(entry: [obj: any, name: string]) {
|
|||
assert.strictEqual(rpcPaths.length, 0, rpcPaths.join('\n'));
|
||||
assert.strictEqual(proxyPaths.length, 0, proxyPaths.join('\n')); // happens...
|
||||
}
|
||||
|
||||
export async function asPromise<T>(event: vscode.Event<T>, timeout = 5000): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
|
||||
const handle = setTimeout(() => {
|
||||
sub.dispose();
|
||||
reject(new Error('asPromise TIMEOUT reached'));
|
||||
}, timeout);
|
||||
|
||||
const sub = event(e => {
|
||||
clearTimeout(handle);
|
||||
sub.dispose();
|
||||
resolve(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,16 +34,6 @@
|
|||
}
|
||||
],
|
||||
"notebookProvider": [
|
||||
{
|
||||
"viewType": "notebookCoreTest",
|
||||
"displayName": "Notebook Core Test",
|
||||
"selector": [
|
||||
{
|
||||
"filenamePattern": "*.vsctestnb",
|
||||
"excludeFileNamePattern": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"viewType": "notebookSmokeTest",
|
||||
"displayName": "Notebook Smoke Test",
|
||||
|
|
|
@ -9,128 +9,6 @@ import { smokeTestActivate } from './notebookSmokeTestMain';
|
|||
export function activate(context: vscode.ExtensionContext): any {
|
||||
smokeTestActivate(context);
|
||||
|
||||
context.subscriptions.push(vscode.notebook.registerNotebookContentProvider('notebookCoreTest', {
|
||||
openNotebook: async (_resource: vscode.Uri): Promise<vscode.NotebookData> => {
|
||||
if (/.*empty\-.*\.vsctestnb$/.test(_resource.path)) {
|
||||
return {
|
||||
metadata: {},
|
||||
cells: []
|
||||
};
|
||||
}
|
||||
|
||||
const dto: vscode.NotebookData = {
|
||||
metadata: {
|
||||
custom: { testMetadata: false }
|
||||
},
|
||||
cells: [
|
||||
{
|
||||
source: 'test',
|
||||
language: 'typescript',
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
outputs: [],
|
||||
metadata: {
|
||||
custom: { testCellMetadata: 123 }
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
return dto;
|
||||
},
|
||||
resolveNotebook: async (_document: vscode.NotebookDocument) => {
|
||||
return;
|
||||
},
|
||||
saveNotebook: async (_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
|
||||
return;
|
||||
},
|
||||
saveNotebookAs: async (_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
|
||||
return;
|
||||
},
|
||||
backupNotebook: async (_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) => {
|
||||
return {
|
||||
id: '1',
|
||||
delete: () => { }
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
const kernel: vscode.NotebookKernel = {
|
||||
id: 'mainKernel',
|
||||
label: 'Notebook Test Kernel',
|
||||
isPreferred: true,
|
||||
supportedLanguages: ['typescript'],
|
||||
executeAllCells: async (_document: vscode.NotebookDocument) => {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
||||
edit.replaceNotebookCellOutput(_document.uri, 0, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined)
|
||||
])]);
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelAllCellsExecution: async (_document: vscode.NotebookDocument) => { },
|
||||
executeCell: async (document: vscode.NotebookDocument, cell: vscode.NotebookCell | undefined) => {
|
||||
if (!cell) {
|
||||
cell = document.cells[0];
|
||||
}
|
||||
|
||||
if (document.uri.path.endsWith('customRenderer.vsctestnb')) {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/custom', ['test'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
}
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
// const previousOutputs = cell.outputs;
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { }
|
||||
};
|
||||
|
||||
const kernel2: vscode.NotebookKernel = {
|
||||
id: 'secondaryKernel',
|
||||
label: 'Notebook Secondary Test Kernel',
|
||||
isPreferred: false,
|
||||
supportedLanguages: ['typescript'],
|
||||
executeAllCells: async (_document: vscode.NotebookDocument) => {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellOutput(_document.uri, 0, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined)
|
||||
])]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelAllCellsExecution: async (_document: vscode.NotebookDocument) => { },
|
||||
executeCell: async (document: vscode.NotebookDocument, cell: vscode.NotebookCell | undefined) => {
|
||||
if (!cell) {
|
||||
cell = document.cells[0];
|
||||
}
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
||||
if (document.uri.path.endsWith('customRenderer.vsctestnb')) {
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/custom', ['test 2'], undefined)
|
||||
])]);
|
||||
} else {
|
||||
edit.replaceNotebookCellOutput(document.uri, cell.index, [new vscode.NotebookCellOutput([
|
||||
new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined)
|
||||
])]);
|
||||
}
|
||||
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
},
|
||||
cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { }
|
||||
};
|
||||
|
||||
context.subscriptions.push(vscode.notebook.registerNotebookKernelProvider({ filenamePattern: '*.vsctestnb' }, {
|
||||
provideKernels: async () => {
|
||||
return [kernel, kernel2];
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"dataFolderName": ".vscode-oss",
|
||||
"win32MutexName": "vscodeoss",
|
||||
"licenseName": "MIT",
|
||||
"licenseUrl": "https://github.com/microsoft/vscode/blob/master/LICENSE.txt",
|
||||
"licenseUrl": "https://github.com/microsoft/vscode/blob/main/LICENSE.txt",
|
||||
"win32DirName": "Microsoft Code OSS",
|
||||
"win32NameVersion": "Microsoft Code OSS",
|
||||
"win32RegValueName": "CodeOSS",
|
||||
|
|
|
@ -14,7 +14,7 @@ header="// Type definitions for Visual Studio Code ${1}
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
* See https://github.com/microsoft/vscode/blob/master/LICENSE.txt for license information.
|
||||
* See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
12
src/main.js
12
src/main.js
|
@ -9,14 +9,14 @@
|
|||
const perf = require('./vs/base/common/performance');
|
||||
perf.mark('code/didStartMain');
|
||||
|
||||
const lp = require('./vs/base/node/languagePacks');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const { getNLSConfiguration } = require('./vs/base/node/languagePacks');
|
||||
const bootstrap = require('./bootstrap');
|
||||
const bootstrapNode = require('./bootstrap-node');
|
||||
const paths = require('./paths');
|
||||
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration> & { applicationName: string}} */
|
||||
const { getDefaultUserDataPath } = require('./vs/base/node/userDataPath');
|
||||
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration>} */
|
||||
const product = require('../product.json');
|
||||
const { app, protocol, crashReporter } = require('electron');
|
||||
|
||||
|
@ -84,7 +84,7 @@ let nlsConfigurationPromise = undefined;
|
|||
const metaDataFile = path.join(__dirname, 'nls.metadata.json');
|
||||
const locale = getUserDefinedLocale(argvConfig);
|
||||
if (locale) {
|
||||
nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
|
||||
nlsConfigurationPromise = getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
|
||||
}
|
||||
|
||||
// Load our code once ready
|
||||
|
@ -405,7 +405,7 @@ function getUserDataPath(cliArgs) {
|
|||
return path.join(portable.portableDataPath, 'user-data');
|
||||
}
|
||||
|
||||
return path.resolve(cliArgs['user-data-dir'] || paths.getDefaultUserDataPath());
|
||||
return path.resolve(cliArgs['user-data-dir'] || getDefaultUserDataPath());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -560,7 +560,7 @@ async function resolveNlsConfiguration() {
|
|||
// See above the comment about the loader and case sensitiviness
|
||||
appLocale = appLocale.toLowerCase();
|
||||
|
||||
nlsConfiguration = await lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
|
||||
nlsConfiguration = await getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
|
||||
if (!nlsConfiguration) {
|
||||
nlsConfiguration = { locale: appLocale, availableLanguages: {} };
|
||||
}
|
||||
|
|
48
src/paths.js
48
src/paths.js
|
@ -1,48 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
const pkg = require('../package.json');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
function getDefaultUserDataPath() {
|
||||
|
||||
// Support global VSCODE_APPDATA environment variable
|
||||
let appDataPath = process.env['VSCODE_APPDATA'];
|
||||
|
||||
// Otherwise check per platform
|
||||
if (!appDataPath) {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
appDataPath = process.env['APPDATA'];
|
||||
if (!appDataPath) {
|
||||
const userProfile = process.env['USERPROFILE'];
|
||||
if (typeof userProfile !== 'string') {
|
||||
throw new Error('Windows: Unexpected undefined %USERPROFILE% environment variable');
|
||||
}
|
||||
appDataPath = path.join(userProfile, 'AppData', 'Roaming');
|
||||
}
|
||||
break;
|
||||
case 'darwin':
|
||||
appDataPath = path.join(os.homedir(), 'Library', 'Application Support');
|
||||
break;
|
||||
case 'linux':
|
||||
appDataPath = process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
|
||||
break;
|
||||
default:
|
||||
throw new Error('Platform not supported');
|
||||
}
|
||||
}
|
||||
|
||||
return path.join(appDataPath, pkg.name);
|
||||
}
|
||||
|
||||
exports.getDefaultUserDataPath = getDefaultUserDataPath;
|
|
@ -383,5 +383,16 @@ export function renderMarkdownAsPlaintext(markdown: IMarkdownString) {
|
|||
if (value.length > 100_000) {
|
||||
value = `${value.substr(0, 100_000)}…`;
|
||||
}
|
||||
return sanitizeRenderedMarkdown({ isTrusted: false }, marked.parse(value, { renderer })).toString();
|
||||
|
||||
const unescapeInfo = new Map<string, string>([
|
||||
['"', '"'],
|
||||
['&', '&'],
|
||||
[''', '\''],
|
||||
['<', '<'],
|
||||
['>', '>'],
|
||||
]);
|
||||
|
||||
const html = marked.parse(value, { renderer }).replace(/&(#\d+|[a-zA-Z]+);/g, m => unescapeInfo.get(m) ?? m);
|
||||
|
||||
return sanitizeRenderedMarkdown({ isTrusted: false }, html).toString();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';
|
|||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
import { $, addDisposableListener, append, EventHelper, EventLike, EventType, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
|
||||
import { $, addDisposableListener, append, EventHelper, EventLike, EventType } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IBaseActionViewItemOptions {
|
||||
draggable?: boolean;
|
||||
|
@ -181,9 +181,9 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
|
|||
}
|
||||
}
|
||||
|
||||
setFocusable(): void {
|
||||
setFocusable(focusable: boolean): void {
|
||||
if (this.element) {
|
||||
this.element.tabIndex = 0;
|
||||
this.element.tabIndex = focusable ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,9 +288,9 @@ export class ActionViewItem extends BaseActionViewItem {
|
|||
}
|
||||
}
|
||||
|
||||
setFocusable(): void {
|
||||
setFocusable(focusable: boolean): void {
|
||||
if (this.label) {
|
||||
this.label.tabIndex = 0;
|
||||
this.label.tabIndex = focusable ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,6 @@ export class ActionViewItem extends BaseActionViewItem {
|
|||
if (this.label) {
|
||||
this.label.setAttribute('aria-disabled', 'true');
|
||||
this.label.classList.add('disabled');
|
||||
removeTabIndexAndUpdateFocus(this.label);
|
||||
}
|
||||
|
||||
if (this.element) {
|
||||
|
|
|
@ -35,7 +35,8 @@ export interface IActionBarOptions {
|
|||
readonly triggerKeys?: ActionTrigger;
|
||||
readonly allowContextMenu?: boolean;
|
||||
readonly preventLoopNavigation?: boolean;
|
||||
readonly ignoreOrientationForPreviousAndNextKey?: boolean;
|
||||
// Pass true here when the up and down keys should not be eaten up by the ActionBar. For example, when an ActionBar is in the list.
|
||||
readonly respectOrientationForPreviousAndNextKey?: boolean;
|
||||
}
|
||||
|
||||
export interface IActionOptions extends IActionViewItemOptions {
|
||||
|
@ -63,6 +64,8 @@ export class ActionBar extends Disposable implements IActionRunner {
|
|||
// Trigger Key Tracking
|
||||
private triggerKeyDown: boolean = false;
|
||||
|
||||
private focusable: boolean = true;
|
||||
|
||||
// Elements
|
||||
domNode: HTMLElement;
|
||||
protected actionsList: HTMLElement;
|
||||
|
@ -117,22 +120,22 @@ export class ActionBar extends Disposable implements IActionRunner {
|
|||
|
||||
switch (this._orientation) {
|
||||
case ActionsOrientation.HORIZONTAL:
|
||||
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.LeftArrow];
|
||||
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.RightArrow];
|
||||
previousKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow] : [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
nextKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.RightArrow] : [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
break;
|
||||
case ActionsOrientation.HORIZONTAL_REVERSE:
|
||||
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.RightArrow];
|
||||
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.LeftArrow];
|
||||
previousKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.RightArrow] : [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
nextKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow] : [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
this.domNode.className += ' reverse';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL:
|
||||
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.UpArrow];
|
||||
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.DownArrow];
|
||||
previousKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.UpArrow] : [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
nextKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.DownArrow] : [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
this.domNode.className += ' vertical';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL_REVERSE:
|
||||
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.DownArrow];
|
||||
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.UpArrow];
|
||||
previousKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.DownArrow] : [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
nextKeys = this.options.respectOrientationForPreviousAndNextKey ? [KeyCode.UpArrow] : [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
this.domNode.className += ' vertical reverse';
|
||||
break;
|
||||
}
|
||||
|
@ -219,6 +222,25 @@ export class ActionBar extends Disposable implements IActionRunner {
|
|||
}
|
||||
}
|
||||
|
||||
// Some action bars should not be focusable at times
|
||||
// When an action bar is not focusable make sure to make all the elements inside it not focusable
|
||||
// When an action bar is focusable again, make sure the first item can be focused
|
||||
setFocusable(focusable: boolean): void {
|
||||
this.focusable = focusable;
|
||||
if (this.focusable) {
|
||||
const first = this.viewItems.find(vi => vi instanceof BaseActionViewItem);
|
||||
if (first instanceof BaseActionViewItem) {
|
||||
first.setFocusable(true);
|
||||
}
|
||||
} else {
|
||||
this.viewItems.forEach(vi => {
|
||||
if (vi instanceof BaseActionViewItem) {
|
||||
vi.setFocusable(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private isTriggerKeyEvent(event: StandardKeyboardEvent): boolean {
|
||||
let ret = false;
|
||||
this._triggerKeys.keys.forEach(keyCode => {
|
||||
|
@ -297,9 +319,9 @@ export class ActionBar extends Disposable implements IActionRunner {
|
|||
item.setActionContext(this.context);
|
||||
item.render(actionViewItemElement);
|
||||
|
||||
if (this.viewItems.every(i => !i.isEnabled()) && item instanceof BaseActionViewItem && item.isEnabled()) {
|
||||
if (this.focusable && this.viewItems.length === 0 && item instanceof BaseActionViewItem) {
|
||||
// We need to allow for the first enabled item to be focused on using tab navigation #106441
|
||||
item.setFocusable();
|
||||
item.setFocusable(true);
|
||||
}
|
||||
|
||||
if (index === null || index < 0 || index >= this.actionsList.children.length) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { Event as BaseEvent, Emitter } from 'vs/base/common/event';
|
|||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch';
|
||||
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
|
||||
import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset } from 'vs/base/browser/dom';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { CSSIcon, Codicon } from 'vs/base/common/codicons';
|
||||
|
@ -214,7 +214,6 @@ export class Button extends Disposable implements IButton {
|
|||
} else {
|
||||
this._element.classList.add('disabled');
|
||||
this._element.setAttribute('aria-disabled', String(true));
|
||||
removeTabIndexAndUpdateFocus(this._element);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./checkbox';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
|
@ -76,6 +75,26 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
|
|||
}
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.checkbox) {
|
||||
this.checkbox.domNode.tabIndex = 0;
|
||||
this.checkbox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (this.checkbox) {
|
||||
this.checkbox.domNode.tabIndex = -1;
|
||||
this.checkbox.domNode.blur();
|
||||
}
|
||||
}
|
||||
|
||||
setFocusable(focusable: boolean): void {
|
||||
if (this.checkbox) {
|
||||
this.checkbox.domNode.tabIndex = focusable ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables.dispose();
|
||||
super.dispose();
|
||||
|
@ -191,12 +210,10 @@ export class Checkbox extends Widget {
|
|||
}
|
||||
|
||||
enable(): void {
|
||||
this.domNode.tabIndex = 0;
|
||||
this.domNode.setAttribute('aria-disabled', String(false));
|
||||
}
|
||||
|
||||
disable(): void {
|
||||
DOM.removeTabIndexAndUpdateFocus(this.domNode);
|
||||
this.domNode.setAttribute('aria-disabled', String(true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,5 +179,4 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem {
|
|||
this.dropdownMenuActionViewItem.render(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -761,6 +761,11 @@ export class DefaultStyleController implements IStyleController {
|
|||
`);
|
||||
}
|
||||
|
||||
if (styles.listInactiveFocusForeground) {
|
||||
content.push(`.monaco-list${suffix} .monaco-list-row.focused { color: ${styles.listInactiveFocusForeground}; }`);
|
||||
content.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { color: ${styles.listInactiveFocusForeground}; }`); // overwrite :hover style in this case!
|
||||
}
|
||||
|
||||
if (styles.listInactiveFocusBackground) {
|
||||
content.push(`.monaco-list${suffix} .monaco-list-row.focused { background-color: ${styles.listInactiveFocusBackground}; }`);
|
||||
content.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { background-color: ${styles.listInactiveFocusBackground}; }`); // overwrite :hover style in this case!
|
||||
|
@ -776,7 +781,7 @@ export class DefaultStyleController implements IStyleController {
|
|||
}
|
||||
|
||||
if (styles.listHoverBackground) {
|
||||
content.push(`.monaco-list${suffix}:not(.drop-target) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`);
|
||||
content.push(`.monaco-list${suffix}:not(.drop-target) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`);
|
||||
}
|
||||
|
||||
if (styles.listHoverForeground) {
|
||||
|
@ -867,6 +872,7 @@ export interface IListStyles {
|
|||
listFocusAndSelectionForeground?: Color;
|
||||
listInactiveSelectionBackground?: Color;
|
||||
listInactiveSelectionForeground?: Color;
|
||||
listInactiveFocusForeground?: Color;
|
||||
listInactiveFocusBackground?: Color;
|
||||
listHoverBackground?: Color;
|
||||
listHoverForeground?: Color;
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as strings from 'vs/base/common/strings';
|
|||
import { IActionRunner, IAction, SubmenuAction, Separator, IActionViewItemProvider, EmptySubmenuAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, addDisposableListener, append, $, clearNode, createStyleSheet, isInShadowDOM, getActiveElement, Dimension, IDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { EventType, EventHelper, EventLike, isAncestor, addDisposableListener, append, $, clearNode, createStyleSheet, isInShadowDOM, getActiveElement, Dimension, IDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
@ -86,6 +86,7 @@ export class Menu extends ActionBar {
|
|||
context: options.context,
|
||||
actionRunner: options.actionRunner,
|
||||
ariaLabel: options.ariaLabel,
|
||||
respectOrientationForPreviousAndNextKey: true,
|
||||
triggerKeys: { keys: [KeyCode.Enter, ...(isMacintosh || isLinux ? [KeyCode.Space] : [])], keyDown: true }
|
||||
});
|
||||
|
||||
|
@ -617,20 +618,23 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
|||
if (this.getAction().enabled) {
|
||||
if (this.element) {
|
||||
this.element.classList.remove('disabled');
|
||||
this.element.removeAttribute('aria-disabled');
|
||||
}
|
||||
|
||||
if (this.item) {
|
||||
this.item.classList.remove('disabled');
|
||||
this.item.removeAttribute('aria-disabled');
|
||||
this.item.tabIndex = 0;
|
||||
}
|
||||
} else {
|
||||
if (this.element) {
|
||||
this.element.classList.add('disabled');
|
||||
this.element.setAttribute('aria-disabled', 'true');
|
||||
}
|
||||
|
||||
if (this.item) {
|
||||
this.item.classList.add('disabled');
|
||||
removeTabIndexAndUpdateFocus(this.item);
|
||||
this.item.setAttribute('aria-disabled', 'true');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
}
|
||||
|
||||
.menubar .menubar-menu-items-holder {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
opacity: 1;
|
||||
z-index: 2000;
|
||||
|
|
|
@ -398,13 +398,21 @@ export class Sash extends Disposable {
|
|||
}));
|
||||
}
|
||||
|
||||
private static onMouseEnter(sash: Sash): void {
|
||||
private static onMouseEnter(sash: Sash, fromLinkedSash: boolean = false): void {
|
||||
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'));
|
||||
|
||||
if (!fromLinkedSash && sash.linkedSash) {
|
||||
Sash.onMouseEnter(sash.linkedSash, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static onMouseLeave(sash: Sash): void {
|
||||
private static onMouseLeave(sash: Sash, fromLinkedSash: boolean = false): void {
|
||||
sash.hoverDelayer.cancel();
|
||||
sash.el.classList.remove('hover');
|
||||
|
||||
if (!fromLinkedSash && sash.linkedSash) {
|
||||
Sash.onMouseLeave(sash.linkedSash, true);
|
||||
}
|
||||
}
|
||||
|
||||
layout(): void {
|
||||
|
|
|
@ -736,8 +736,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
|||
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(e => this.onEnter(e), this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Escape).on(e => this.onEscape(e), this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(this.onUpArrow, this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(this.onDownArrow, this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(e => this.onUpArrow(e), this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(e => this.onDownArrow(e), this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageDown).on(this.onPageDown, this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageUp).on(this.onPageUp, this));
|
||||
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Home).on(this.onHome, this));
|
||||
|
@ -916,8 +916,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
|||
}
|
||||
|
||||
// List navigation - have to handle a disabled option (jump over)
|
||||
private onDownArrow(): void {
|
||||
private onDownArrow(e: StandardKeyboardEvent): void {
|
||||
if (this.selected < this.options.length - 1) {
|
||||
dom.EventHelper.stop(e, true);
|
||||
|
||||
// Skip disabled options
|
||||
const nextOptionDisabled = this.options[this.selected + 1].isDisabled;
|
||||
|
@ -937,8 +938,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
|||
}
|
||||
}
|
||||
|
||||
private onUpArrow(): void {
|
||||
private onUpArrow(e: StandardKeyboardEvent): void {
|
||||
if (this.selected > 0) {
|
||||
dom.EventHelper.stop(e, true);
|
||||
// Skip disabled options
|
||||
const previousOptionDisabled = this.options[this.selected - 1].isDisabled;
|
||||
if (previousOptionDisabled && this.selected > 1) {
|
||||
|
|
|
@ -28,6 +28,7 @@ export interface IToolBarOptions {
|
|||
anchorAlignmentProvider?: () => AnchorAlignment;
|
||||
renderDropdownAsChildElement?: boolean;
|
||||
moreIcon?: CSSIcon;
|
||||
readonly respectOrientationForPreviousAndNextKey?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,6 +64,7 @@ export class ToolBar extends Disposable {
|
|||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionRunner: options.actionRunner,
|
||||
respectOrientationForPreviousAndNextKey: options.respectOrientationForPreviousAndNextKey,
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action.id === ToggleMenuAction.ID) {
|
||||
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
|
||||
|
|
|
@ -961,7 +961,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
|
|||
readonly filterOnType?: boolean;
|
||||
readonly smoothScrolling?: boolean;
|
||||
readonly horizontalScrolling?: boolean;
|
||||
readonly expandOnlyOnDoubleClick?: boolean;
|
||||
readonly expandOnDoubleClick?: boolean;
|
||||
readonly expandOnlyOnTwistieClick?: boolean | ((e: any) => boolean); // e is T
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
|||
return super.onViewPointer(e);
|
||||
}
|
||||
|
||||
if (this.tree.expandOnlyOnDoubleClick && e.browserEvent.detail !== 2 && !onTwistie) {
|
||||
if (!this.tree.expandOnDoubleClick && e.browserEvent.detail === 2) {
|
||||
return super.onViewPointer(e);
|
||||
}
|
||||
|
||||
|
@ -1129,6 +1129,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
|||
const model = ((this.tree as any).model as ITreeModel<T, TFilterData, TRef>); // internal
|
||||
const location = model.getNodeLocation(node);
|
||||
const recursive = e.browserEvent.altKey;
|
||||
this.tree.setFocus([location]);
|
||||
model.setCollapsed(location, undefined, recursive);
|
||||
|
||||
if (expandOnlyOnTwistieClick && onTwistie) {
|
||||
|
@ -1142,7 +1143,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
|||
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
|
||||
const onTwistie = (e.browserEvent.target as HTMLElement).classList.contains('monaco-tl-twistie');
|
||||
|
||||
if (onTwistie) {
|
||||
if (onTwistie || !this.tree.expandOnDoubleClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1262,8 +1263,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
|||
get filterOnType(): boolean { return !!this._options.filterOnType; }
|
||||
get onDidChangeTypeFilterPattern(): Event<string> { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; }
|
||||
|
||||
get expandOnlyOnDoubleClick(): boolean { return this._options.expandOnlyOnDoubleClick ?? false; }
|
||||
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; }
|
||||
get expandOnDoubleClick(): boolean { return typeof this._options.expandOnDoubleClick === 'undefined' ? true : this._options.expandOnDoubleClick; }
|
||||
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? true : this._options.expandOnlyOnTwistieClick; }
|
||||
|
||||
private readonly _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
|
||||
readonly onDidUpdateOptions: Event<IAbstractTreeOptions<T, TFilterData>> = this._onDidUpdateOptions.event;
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-tl-twistie::before {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.monaco-tl-twistie.collapsed::before {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
|||
/**
|
||||
* @returns whether the provided parameter is a JavaScript Array or not.
|
||||
*/
|
||||
export function isArray<T>(array: T | {}): array is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[] {
|
||||
export function isArray(array: any): array is any[] {
|
||||
return Array.isArray(array);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,256 +3,257 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="../../../typings/require.d.ts" />
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @param {NodeRequire} nodeRequire
|
||||
* @param {typeof import('path')} path
|
||||
* @param {typeof import('fs')} fs
|
||||
* @param {typeof import('../common/performance')} perf
|
||||
*/
|
||||
function factory(nodeRequire, path, fs, perf) {
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<boolean>}
|
||||
* @param {NodeRequire} nodeRequire
|
||||
* @param {typeof import('path')} path
|
||||
* @param {typeof import('fs')} fs
|
||||
* @param {typeof import('../common/performance')} perf
|
||||
*/
|
||||
function exists(file) {
|
||||
return new Promise(c => fs.exists(file, c));
|
||||
}
|
||||
function factory(nodeRequire, path, fs, perf) {
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function touch(file) {
|
||||
return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} dir
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function mkdirp(dir) {
|
||||
return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} location
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function rimraf(location) {
|
||||
return new Promise((c, e) => fs.rmdir(location, { recursive: true }, err => (err && err.code !== 'ENOENT') ? e(err) : c()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function readFile(file) {
|
||||
return new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @param {string} content
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function writeFile(file, content) {
|
||||
return new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} userDataPath
|
||||
* @returns {object}
|
||||
*/
|
||||
function getLanguagePackConfigurations(userDataPath) {
|
||||
const configFile = path.join(userDataPath, 'languagepacks.json');
|
||||
try {
|
||||
return nodeRequire(configFile);
|
||||
} catch (err) {
|
||||
// Do nothing. If we can't read the file we have no
|
||||
// language pack config.
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
function exists(file) {
|
||||
return new Promise(c => fs.exists(file, c));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} config
|
||||
* @param {string} locale
|
||||
*/
|
||||
function resolveLanguagePackLocale(config, locale) {
|
||||
try {
|
||||
while (locale) {
|
||||
if (config[locale]) {
|
||||
return locale;
|
||||
} else {
|
||||
const index = locale.lastIndexOf('-');
|
||||
if (index > 0) {
|
||||
locale = locale.substring(0, index);
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function touch(file) {
|
||||
return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} dir
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function mkdirp(dir) {
|
||||
return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} location
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function rimraf(location) {
|
||||
return new Promise((c, e) => fs.rmdir(location, { recursive: true }, err => (err && err.code !== 'ENOENT') ? e(err) : c()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function readFile(file) {
|
||||
return new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @param {string} content
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function writeFile(file, content) {
|
||||
return new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} userDataPath
|
||||
* @returns {object}
|
||||
*/
|
||||
function getLanguagePackConfigurations(userDataPath) {
|
||||
const configFile = path.join(userDataPath, 'languagepacks.json');
|
||||
try {
|
||||
return nodeRequire(configFile);
|
||||
} catch (err) {
|
||||
// Do nothing. If we can't read the file we have no
|
||||
// language pack config.
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} config
|
||||
* @param {string} locale
|
||||
*/
|
||||
function resolveLanguagePackLocale(config, locale) {
|
||||
try {
|
||||
while (locale) {
|
||||
if (config[locale]) {
|
||||
return locale;
|
||||
} else {
|
||||
return undefined;
|
||||
const index = locale.lastIndexOf('-');
|
||||
if (index > 0) {
|
||||
locale = locale.substring(0, index);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Resolving language pack configuration failed.', err);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Resolving language pack configuration failed.', err);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} commit
|
||||
* @param {string} userDataPath
|
||||
* @param {string} metaDataFile
|
||||
* @param {string} locale
|
||||
*/
|
||||
function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
|
||||
if (locale === 'pseudo') {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (process.env['VSCODE_DEV']) {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
}
|
||||
|
||||
// We have a built version so we have extracted nls file. Try to find
|
||||
// the right file to use.
|
||||
|
||||
// Check if we have an English or English US locale. If so fall to default since that is our
|
||||
// English translation (we don't ship *.nls.en.json files)
|
||||
if (locale && (locale === 'en' || locale === 'en-us')) {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
}
|
||||
|
||||
const initialLocale = locale;
|
||||
|
||||
perf.mark('code/willGenerateNls');
|
||||
|
||||
const defaultResult = function (locale) {
|
||||
perf.mark('code/didGenerateNls');
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
};
|
||||
try {
|
||||
if (!commit) {
|
||||
return defaultResult(initialLocale);
|
||||
/**
|
||||
* @param {string} commit
|
||||
* @param {string} userDataPath
|
||||
* @param {string} metaDataFile
|
||||
* @param {string} locale
|
||||
*/
|
||||
function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
|
||||
if (locale === 'pseudo') {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
|
||||
}
|
||||
const configs = getLanguagePackConfigurations(userDataPath);
|
||||
if (!configs) {
|
||||
return defaultResult(initialLocale);
|
||||
|
||||
if (process.env['VSCODE_DEV']) {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
}
|
||||
locale = resolveLanguagePackLocale(configs, locale);
|
||||
if (!locale) {
|
||||
return defaultResult(initialLocale);
|
||||
|
||||
// We have a built version so we have extracted nls file. Try to find
|
||||
// the right file to use.
|
||||
|
||||
// Check if we have an English or English US locale. If so fall to default since that is our
|
||||
// English translation (we don't ship *.nls.en.json files)
|
||||
if (locale && (locale === 'en' || locale === 'en-us')) {
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
}
|
||||
const packConfig = configs[locale];
|
||||
let mainPack;
|
||||
if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
return exists(mainPack).then(fileExists => {
|
||||
if (!fileExists) {
|
||||
|
||||
const initialLocale = locale;
|
||||
|
||||
perf.mark('code/willGenerateNls');
|
||||
|
||||
const defaultResult = function (locale) {
|
||||
perf.mark('code/didGenerateNls');
|
||||
return Promise.resolve({ locale: locale, availableLanguages: {} });
|
||||
};
|
||||
try {
|
||||
if (!commit) {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
const packId = packConfig.hash + '.' + locale;
|
||||
const cacheRoot = path.join(userDataPath, 'clp', packId);
|
||||
const coreLocation = path.join(cacheRoot, commit);
|
||||
const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
|
||||
const corruptedFile = path.join(cacheRoot, 'corrupted.info');
|
||||
const result = {
|
||||
locale: initialLocale,
|
||||
availableLanguages: { '*': locale },
|
||||
_languagePackId: packId,
|
||||
_translationsConfigFile: translationsConfigFile,
|
||||
_cacheRoot: cacheRoot,
|
||||
_resolvedLanguagePackCoreLocation: coreLocation,
|
||||
_corruptedFile: corruptedFile
|
||||
};
|
||||
return exists(corruptedFile).then(corrupted => {
|
||||
// The nls cache directory is corrupted.
|
||||
let toDelete;
|
||||
if (corrupted) {
|
||||
toDelete = rimraf(cacheRoot);
|
||||
} else {
|
||||
toDelete = Promise.resolve(undefined);
|
||||
const configs = getLanguagePackConfigurations(userDataPath);
|
||||
if (!configs) {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
locale = resolveLanguagePackLocale(configs, locale);
|
||||
if (!locale) {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
const packConfig = configs[locale];
|
||||
let mainPack;
|
||||
if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
return exists(mainPack).then(fileExists => {
|
||||
if (!fileExists) {
|
||||
return defaultResult(initialLocale);
|
||||
}
|
||||
return toDelete.then(() => {
|
||||
return exists(coreLocation).then(fileExists => {
|
||||
if (fileExists) {
|
||||
// We don't wait for this. No big harm if we can't touch
|
||||
touch(coreLocation).catch(() => { });
|
||||
perf.mark('code/didGenerateNls');
|
||||
return result;
|
||||
}
|
||||
return mkdirp(coreLocation).then(() => {
|
||||
return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
|
||||
}).then(values => {
|
||||
const metadata = JSON.parse(values[0]);
|
||||
const packData = JSON.parse(values[1]).contents;
|
||||
const bundles = Object.keys(metadata.bundles);
|
||||
const writes = [];
|
||||
for (const bundle of bundles) {
|
||||
const modules = metadata.bundles[bundle];
|
||||
const target = Object.create(null);
|
||||
for (const module of modules) {
|
||||
const keys = metadata.keys[module];
|
||||
const defaultMessages = metadata.messages[module];
|
||||
const translations = packData[module];
|
||||
let targetStrings;
|
||||
if (translations) {
|
||||
targetStrings = [];
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const elem = keys[i];
|
||||
const key = typeof elem === 'string' ? elem : elem.key;
|
||||
let translatedMessage = translations[key];
|
||||
if (translatedMessage === undefined) {
|
||||
translatedMessage = defaultMessages[i];
|
||||
}
|
||||
targetStrings.push(translatedMessage);
|
||||
}
|
||||
} else {
|
||||
targetStrings = defaultMessages;
|
||||
}
|
||||
target[module] = targetStrings;
|
||||
}
|
||||
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
|
||||
const packId = packConfig.hash + '.' + locale;
|
||||
const cacheRoot = path.join(userDataPath, 'clp', packId);
|
||||
const coreLocation = path.join(cacheRoot, commit);
|
||||
const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
|
||||
const corruptedFile = path.join(cacheRoot, 'corrupted.info');
|
||||
const result = {
|
||||
locale: initialLocale,
|
||||
availableLanguages: { '*': locale },
|
||||
_languagePackId: packId,
|
||||
_translationsConfigFile: translationsConfigFile,
|
||||
_cacheRoot: cacheRoot,
|
||||
_resolvedLanguagePackCoreLocation: coreLocation,
|
||||
_corruptedFile: corruptedFile
|
||||
};
|
||||
return exists(corruptedFile).then(corrupted => {
|
||||
// The nls cache directory is corrupted.
|
||||
let toDelete;
|
||||
if (corrupted) {
|
||||
toDelete = rimraf(cacheRoot);
|
||||
} else {
|
||||
toDelete = Promise.resolve(undefined);
|
||||
}
|
||||
return toDelete.then(() => {
|
||||
return exists(coreLocation).then(fileExists => {
|
||||
if (fileExists) {
|
||||
// We don't wait for this. No big harm if we can't touch
|
||||
touch(coreLocation).catch(() => { });
|
||||
perf.mark('code/didGenerateNls');
|
||||
return result;
|
||||
}
|
||||
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
|
||||
return Promise.all(writes);
|
||||
}).then(() => {
|
||||
perf.mark('code/didGenerateNls');
|
||||
return result;
|
||||
}).catch(err => {
|
||||
console.error('Generating translation files failed.', err);
|
||||
return defaultResult(locale);
|
||||
return mkdirp(coreLocation).then(() => {
|
||||
return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
|
||||
}).then(values => {
|
||||
const metadata = JSON.parse(values[0]);
|
||||
const packData = JSON.parse(values[1]).contents;
|
||||
const bundles = Object.keys(metadata.bundles);
|
||||
const writes = [];
|
||||
for (const bundle of bundles) {
|
||||
const modules = metadata.bundles[bundle];
|
||||
const target = Object.create(null);
|
||||
for (const module of modules) {
|
||||
const keys = metadata.keys[module];
|
||||
const defaultMessages = metadata.messages[module];
|
||||
const translations = packData[module];
|
||||
let targetStrings;
|
||||
if (translations) {
|
||||
targetStrings = [];
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const elem = keys[i];
|
||||
const key = typeof elem === 'string' ? elem : elem.key;
|
||||
let translatedMessage = translations[key];
|
||||
if (translatedMessage === undefined) {
|
||||
translatedMessage = defaultMessages[i];
|
||||
}
|
||||
targetStrings.push(translatedMessage);
|
||||
}
|
||||
} else {
|
||||
targetStrings = defaultMessages;
|
||||
}
|
||||
target[module] = targetStrings;
|
||||
}
|
||||
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
|
||||
}
|
||||
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
|
||||
return Promise.all(writes);
|
||||
}).then(() => {
|
||||
perf.mark('code/didGenerateNls');
|
||||
return result;
|
||||
}).catch(err => {
|
||||
console.error('Generating translation files failed.', err);
|
||||
return defaultResult(locale);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Generating translation files failed.', err);
|
||||
return defaultResult(locale);
|
||||
} catch (err) {
|
||||
console.error('Generating translation files failed.', err);
|
||||
return defaultResult(locale);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
getNLSConfiguration
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
getNLSConfiguration
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
if (typeof define === 'function') {
|
||||
// amd
|
||||
// @ts-ignore
|
||||
define(['path', 'fs', 'vs/base/common/performance'], function (path, fs, perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const perf = require('../common/performance');
|
||||
module.exports = factory(require, path, fs, perf);
|
||||
} else {
|
||||
throw new Error('Unknown context');
|
||||
}
|
||||
if (typeof define === 'function') {
|
||||
// amd
|
||||
define(['require', 'path', 'fs', 'vs/base/common/performance'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('fs')} */ fs, /** @type {typeof import('../common/performance')} */ perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const perf = require('../common/performance');
|
||||
module.exports = factory(require, path, fs, perf);
|
||||
} else {
|
||||
throw new Error('Unknown context');
|
||||
}
|
||||
}());
|
||||
|
|
9
src/vs/base/node/userDataPath.d.ts
vendored
Normal file
9
src/vs/base/node/userDataPath.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Returns the user data path to use.
|
||||
*/
|
||||
export function getDefaultUserDataPath(): string;
|
72
src/vs/base/node/userDataPath.js
Normal file
72
src/vs/base/node/userDataPath.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="../../../typings/require.d.ts" />
|
||||
|
||||
//@ts-check
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @param {typeof import('path')} path
|
||||
* @param {typeof import('os')} os
|
||||
* @param {string} productName
|
||||
*/
|
||||
function factory(path, os, productName) {
|
||||
|
||||
function getDefaultUserDataPath() {
|
||||
|
||||
// Support global VSCODE_APPDATA environment variable
|
||||
let appDataPath = process.env['VSCODE_APPDATA'];
|
||||
|
||||
// Otherwise check per platform
|
||||
if (!appDataPath) {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
appDataPath = process.env['APPDATA'];
|
||||
if (!appDataPath) {
|
||||
const userProfile = process.env['USERPROFILE'];
|
||||
if (typeof userProfile !== 'string') {
|
||||
throw new Error('Windows: Unexpected undefined %USERPROFILE% environment variable');
|
||||
}
|
||||
appDataPath = path.join(userProfile, 'AppData', 'Roaming');
|
||||
}
|
||||
break;
|
||||
case 'darwin':
|
||||
appDataPath = path.join(os.homedir(), 'Library', 'Application Support');
|
||||
break;
|
||||
case 'linux':
|
||||
appDataPath = process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
|
||||
break;
|
||||
default:
|
||||
throw new Error('Platform not supported');
|
||||
}
|
||||
}
|
||||
|
||||
return path.join(appDataPath, productName);
|
||||
}
|
||||
|
||||
return {
|
||||
getDefaultUserDataPath
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof define === 'function') {
|
||||
define(['require', 'path', 'os', 'vs/base/common/network', 'vs/base/common/resources'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('os')} */ os, /** @type {typeof import('../common/network')} */ network, /** @type {typeof import("../common/resources")} */ resources) {
|
||||
const rootPath = resources.dirname(network.FileAccess.asFileUri('', require));
|
||||
const pkg = require.__$__nodeRequire(resources.joinPath(rootPath, 'package.json').fsPath);
|
||||
|
||||
return factory(path, os, pkg.name);
|
||||
}); // amd
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
const pkg = require('../../../../package.json');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
module.exports = factory(path, os, pkg.name); // commonjs
|
||||
} else {
|
||||
throw new Error('Unknown context');
|
||||
}
|
||||
}());
|
|
@ -56,7 +56,7 @@ export interface IQuickInputStyles {
|
|||
countBadge: ICountBadgetyles;
|
||||
button: IButtonStyles;
|
||||
progressBar: IProgressBarStyles;
|
||||
list: IListStyles & { listInactiveFocusForeground?: Color; pickerGroupBorder?: Color; pickerGroupForeground?: Color; };
|
||||
list: IListStyles & { pickerGroupBorder?: Color; pickerGroupForeground?: Color; };
|
||||
}
|
||||
|
||||
export interface IQuickInputWidgetStyles {
|
||||
|
@ -1706,10 +1706,6 @@ export class QuickInputController extends Disposable {
|
|||
this.ui.list.style(this.styles.list);
|
||||
|
||||
const content: string[] = [];
|
||||
if (this.styles.list.listInactiveFocusForeground) {
|
||||
content.push(`.monaco-list .monaco-list-row.focused { color: ${this.styles.list.listInactiveFocusForeground}; }`);
|
||||
content.push(`.monaco-list .monaco-list-row.focused:hover { color: ${this.styles.list.listInactiveFocusForeground}; }`); // overwrite :hover style in this case!
|
||||
}
|
||||
if (this.styles.list.pickerGroupBorder) {
|
||||
content.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.list.pickerGroupBorder}; }`);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ export class Storage extends Disposable implements IStorage {
|
|||
private pendingDeletes = new Set<string>();
|
||||
private pendingInserts = new Map<string, string>();
|
||||
|
||||
private pendingClose: Promise<void> | undefined = undefined;
|
||||
|
||||
private readonly whenFlushedCallbacks: Function[] = [];
|
||||
|
||||
constructor(
|
||||
|
@ -256,10 +258,15 @@ export class Storage extends Disposable implements IStorage {
|
|||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
if (this.state === StorageState.Closed) {
|
||||
return; // return if already closed
|
||||
if (!this.pendingClose) {
|
||||
this.pendingClose = this.doClose();
|
||||
}
|
||||
|
||||
return this.pendingClose;
|
||||
}
|
||||
|
||||
private async doClose(): Promise<void> {
|
||||
|
||||
// Update state
|
||||
this.state = StorageState.Closed;
|
||||
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { FileAccess } from 'vs/base/common/network';
|
||||
import * as assert from 'assert';
|
||||
import { getDefaultUserDataPath } from 'vs/base/node/userDataPath';
|
||||
|
||||
const pathsPath = FileAccess.asFileUri('paths', require).fsPath;
|
||||
const paths = require.__$__nodeRequire<{ getDefaultUserDataPath(): string }>(pathsPath);
|
||||
suite('User data path', () => {
|
||||
|
||||
export const getDefaultUserDataPath = paths.getDefaultUserDataPath;
|
||||
test('getDefaultUserDataPath', () => {
|
||||
const path = getDefaultUserDataPath();
|
||||
assert.ok(path.length > 0);
|
||||
});
|
||||
});
|
|
@ -4,9 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const bootstrap = bootstrapLib();
|
||||
const bootstrapWindow = bootstrapWindowLib();
|
||||
|
||||
|
@ -38,5 +38,4 @@
|
|||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
}());
|
||||
|
|
|
@ -58,8 +58,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
|||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
|
||||
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
|
||||
import { NativeStorageService } from 'vs/platform/storage/node/storageService';
|
||||
import { GlobalStorageDatabaseChannelClient } from 'vs/platform/storage/node/storageIpc';
|
||||
import { NativeStorageService2 } from 'vs/platform/storage/electron-sandbox/storageService2';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
|
||||
import { UserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSyncResourceEnablementService';
|
||||
|
@ -175,8 +174,8 @@ class SharedProcessMain extends Disposable {
|
|||
|
||||
await configurationService.initialize();
|
||||
|
||||
// Storage
|
||||
const storageService = new NativeStorageService(new GlobalStorageDatabaseChannelClient(mainProcessService.getChannel('storage')), logService, environmentService);
|
||||
// Storage (global access only)
|
||||
const storageService = new NativeStorageService2(undefined, mainProcessService, environmentService);
|
||||
services.set(IStorageService, storageService);
|
||||
|
||||
await storageService.initialize();
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
/// <reference path="../../../../typings/require.d.ts" />
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const bootstrapWindow = bootstrapWindowLib();
|
||||
|
||||
// Add a perf entry right from the top
|
||||
|
@ -179,5 +179,4 @@
|
|||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
}());
|
||||
|
|
|
@ -58,8 +58,8 @@ import { joinPath } from 'vs/base/common/resources';
|
|||
import { localize } from 'vs/nls';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { SnapUpdateService } from 'vs/platform/update/electron-main/updateService.snap';
|
||||
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/node/storageMainService';
|
||||
import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIpc';
|
||||
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
|
||||
import { StorageDatabaseChannel } from 'vs/platform/storage/electron-main/storageIpc';
|
||||
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
|
||||
import { IBackupMainService } from 'vs/platform/backup/electron-main/backup';
|
||||
import { WorkspacesHistoryMainService, IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
|
||||
|
@ -102,7 +102,7 @@ export class CodeApplication extends Disposable {
|
|||
private readonly userEnv: IProcessEnvironment,
|
||||
@IInstantiationService private readonly mainInstantiationService: IInstantiationService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IEnvironmentMainService private readonly environmentService: IEnvironmentMainService,
|
||||
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IStateService private readonly stateService: IStateService,
|
||||
|
@ -168,7 +168,7 @@ export class CodeApplication extends Disposable {
|
|||
event.preventDefault();
|
||||
});
|
||||
app.on('remote-get-current-web-contents', event => {
|
||||
if (this.environmentService.args.driver) {
|
||||
if (this.environmentMainService.args.driver) {
|
||||
return; // the driver needs access to web contents
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ export class CodeApplication extends Disposable {
|
|||
}
|
||||
|
||||
const srcUri = uri.fsPath.toLowerCase();
|
||||
const rootUri = URI.file(this.environmentService.appRoot).fsPath.toLowerCase();
|
||||
const rootUri = URI.file(this.environmentMainService.appRoot).fsPath.toLowerCase();
|
||||
|
||||
return srcUri.startsWith(rootUri + sep);
|
||||
};
|
||||
|
@ -255,7 +255,7 @@ export class CodeApplication extends Disposable {
|
|||
runningTimeout = setTimeout(() => {
|
||||
this.windowsMainService?.open({
|
||||
context: OpenContext.DOCK /* can also be opening from finder while app is running */,
|
||||
cli: this.environmentService.args,
|
||||
cli: this.environmentMainService.args,
|
||||
urisToOpen: macOpenFileURIs,
|
||||
gotoLineMode: false,
|
||||
preferNewWindow: true /* dropping on the dock or opening from finder prefers to open in a new window */
|
||||
|
@ -328,7 +328,7 @@ export class CodeApplication extends Disposable {
|
|||
args = window.config;
|
||||
env = { ...process.env, ...window.config.userEnv };
|
||||
} else {
|
||||
args = this.environmentService.args;
|
||||
args = this.environmentMainService.args;
|
||||
env = process.env;
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,7 @@ export class CodeApplication extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof path !== 'string' || !isAbsolute(path) || !isEqualOrParent(path, this.environmentService.cachedLanguagesPath, !isLinux)) {
|
||||
if (typeof path !== 'string' || !isAbsolute(path) || !isEqualOrParent(path, this.environmentMainService.cachedLanguagesPath, !isLinux)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -404,8 +404,8 @@ export class CodeApplication extends Disposable {
|
|||
|
||||
async startup(): Promise<void> {
|
||||
this.logService.debug('Starting VS Code');
|
||||
this.logService.debug(`from: ${this.environmentService.appRoot}`);
|
||||
this.logService.debug('args:', this.environmentService.args);
|
||||
this.logService.debug(`from: ${this.environmentMainService.appRoot}`);
|
||||
this.logService.debug('args:', this.environmentMainService.args);
|
||||
|
||||
// Make sure we associate the program with the app user model id
|
||||
// This will help Windows to associate the running program with
|
||||
|
@ -448,10 +448,10 @@ export class CodeApplication extends Disposable {
|
|||
const appInstantiationService = await this.initServices(machineId, sharedProcess, sharedProcessReady);
|
||||
|
||||
// Create driver
|
||||
if (this.environmentService.driverHandle) {
|
||||
const server = await serveDriver(mainProcessElectronServer, this.environmentService.driverHandle, this.environmentService, appInstantiationService);
|
||||
if (this.environmentMainService.driverHandle) {
|
||||
const server = await serveDriver(mainProcessElectronServer, this.environmentMainService.driverHandle, this.environmentMainService, appInstantiationService);
|
||||
|
||||
this.logService.info('Driver started at:', this.environmentService.driverHandle);
|
||||
this.logService.info('Driver started at:', this.environmentMainService.driverHandle);
|
||||
this._register(server);
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,7 @@ export class CodeApplication extends Disposable {
|
|||
appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor));
|
||||
|
||||
// Tracing: Stop tracing after windows are ready if enabled
|
||||
if (this.environmentService.args.trace) {
|
||||
if (this.environmentMainService.args.trace) {
|
||||
appInstantiationService.invokeFunction(accessor => this.stopTracingEventually(accessor, windows));
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ export class CodeApplication extends Disposable {
|
|||
// Spawn shared process after the first window has opened and 3s have passed
|
||||
this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => {
|
||||
this._register(new RunOnceScheduler(async () => {
|
||||
sharedProcess.spawn(await resolveShellEnv(this.logService, this.environmentService.args, process.env));
|
||||
sharedProcess.spawn(await resolveShellEnv(this.logService, this.environmentMainService.args, process.env));
|
||||
}, 3000)).schedule();
|
||||
});
|
||||
|
||||
|
@ -580,23 +580,21 @@ export class CodeApplication extends Disposable {
|
|||
services.set(IExtensionUrlTrustService, new SyncDescriptor(ExtensionUrlTrustService));
|
||||
|
||||
// Storage
|
||||
const storageMainService = new StorageMainService(this.logService, this.environmentService);
|
||||
services.set(IStorageMainService, storageMainService);
|
||||
this.lifecycleMainService.onWillShutdown(e => e.join(storageMainService.close()));
|
||||
services.set(IStorageMainService, new SyncDescriptor(StorageMainService));
|
||||
|
||||
// Backups
|
||||
const backupMainService = new BackupMainService(this.environmentService, this.configurationService, this.logService);
|
||||
const backupMainService = new BackupMainService(this.environmentMainService, this.configurationService, this.logService);
|
||||
services.set(IBackupMainService, backupMainService);
|
||||
|
||||
// URL handling
|
||||
services.set(IURLService, new SyncDescriptor(NativeURLService));
|
||||
|
||||
// Telemetry
|
||||
if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
|
||||
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!product.enableTelemetry) {
|
||||
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, product.commit, product.version, machineId, product.msftInternalDomains, this.environmentService.installSourcePath);
|
||||
const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath];
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, product.commit, product.version, machineId, product.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
|
||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config]));
|
||||
|
@ -666,7 +664,7 @@ export class CodeApplication extends Disposable {
|
|||
mainProcessElectronServer.registerChannel('webview', webviewChannel);
|
||||
|
||||
// Storage (main & shared process)
|
||||
const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, accessor.get(IStorageMainService)));
|
||||
const storageChannel = this._register(new StorageDatabaseChannel(this.logService, accessor.get(IStorageMainService)));
|
||||
mainProcessElectronServer.registerChannel('storage', storageChannel);
|
||||
sharedProcessClient.then(client => client.registerChannel('storage', storageChannel));
|
||||
|
||||
|
@ -699,7 +697,7 @@ export class CodeApplication extends Disposable {
|
|||
const pendingWindowOpenablesFromProtocolLinks: IWindowOpenable[] = [];
|
||||
const pendingProtocolLinksToHandle = [
|
||||
// Windows/Linux: protocol handler invokes CLI with --open-url
|
||||
...this.environmentService.args['open-url'] ? this.environmentService.args._urls || [] : [],
|
||||
...this.environmentMainService.args['open-url'] ? this.environmentMainService.args._urls || [] : [],
|
||||
|
||||
// macOS: open-url events
|
||||
...((<any>global).getOpenUrls() || []) as string[]
|
||||
|
@ -736,7 +734,7 @@ export class CodeApplication extends Disposable {
|
|||
// or open new windows. The URL handler will be invoked from
|
||||
// protocol invocations outside of VSCode.
|
||||
const app = this;
|
||||
const environmentService = this.environmentService;
|
||||
const environmentService = this.environmentMainService;
|
||||
urlService.registerHandler({
|
||||
async handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
|
||||
|
||||
|
@ -791,10 +789,10 @@ export class CodeApplication extends Disposable {
|
|||
urlService.registerHandler(new URLHandlerChannelClient(urlHandlerChannel));
|
||||
|
||||
// Watch Electron URLs and forward them to the UrlService
|
||||
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentService));
|
||||
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService));
|
||||
|
||||
// Open our first window
|
||||
const args = this.environmentService.args;
|
||||
const args = this.environmentMainService.args;
|
||||
const macOpenFiles: string[] = (<any>global).macOpenFiles;
|
||||
const context = isLaunchedFromCli(process.env) ? OpenContext.CLI : OpenContext.DESKTOP;
|
||||
const hasCliArgs = args._.length;
|
||||
|
@ -864,7 +862,7 @@ export class CodeApplication extends Disposable {
|
|||
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")),
|
||||
],
|
||||
cancelId: 1,
|
||||
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentService), product.nameShort),
|
||||
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), product.nameShort),
|
||||
detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"),
|
||||
noLink: true
|
||||
});
|
||||
|
@ -960,13 +958,13 @@ export class CodeApplication extends Disposable {
|
|||
}
|
||||
|
||||
// Start to fetch shell environment (if needed) after window has opened
|
||||
resolveShellEnv(this.logService, this.environmentService.args, process.env);
|
||||
resolveShellEnv(this.logService, this.environmentMainService.args, process.env);
|
||||
|
||||
// If enable-crash-reporter argv is undefined then this is a fresh start,
|
||||
// based on telemetry.enableCrashreporter settings, generate a UUID which
|
||||
// will be used as crash reporter id and also update the json file.
|
||||
try {
|
||||
const argvContent = await this.fileService.readFile(this.environmentService.argvResource);
|
||||
const argvContent = await this.fileService.readFile(this.environmentMainService.argvResource);
|
||||
const argvString = argvContent.value.toString();
|
||||
const argvJSON = JSON.parse(stripComments(argvString));
|
||||
if (argvJSON['enable-crash-reporter'] === undefined) {
|
||||
|
@ -984,7 +982,7 @@ export class CodeApplication extends Disposable {
|
|||
];
|
||||
const newArgvString = argvString.substring(0, argvString.length - 2).concat(',\n', additionalArgvContent.join('\n'));
|
||||
|
||||
await this.fileService.writeFile(this.environmentService.argvResource, VSBuffer.fromString(newArgvString));
|
||||
await this.fileService.writeFile(this.environmentMainService.argvResource, VSBuffer.fromString(newArgvString));
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
|
@ -1004,7 +1002,7 @@ export class CodeApplication extends Disposable {
|
|||
|
||||
recordingStopped = true; // only once
|
||||
|
||||
const path = await contentTracing.stopRecording(joinPath(this.environmentService.userHome, `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
|
||||
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
|
||||
|
||||
if (!timeout) {
|
||||
dialogMainService.showMessageBox({
|
||||
|
|
|
@ -201,7 +201,7 @@ export class ProxyAuthHandler extends Disposable {
|
|||
const proxyAuthResponseHandler = async (event: ElectronEvent, channel: string, reply: Credentials & { remember: boolean } | undefined /* canceled */) => {
|
||||
if (channel === payload.replyChannel) {
|
||||
this.logService.trace(`auth#doResolveProxyCredentials - exit - received credentials from window ${window.id}`);
|
||||
window.win.webContents.off('ipc-message', proxyAuthResponseHandler);
|
||||
window.win?.webContents.off('ipc-message', proxyAuthResponseHandler);
|
||||
|
||||
// We got credentials from the window
|
||||
if (reply) {
|
||||
|
@ -229,7 +229,7 @@ export class ProxyAuthHandler extends Disposable {
|
|||
}
|
||||
};
|
||||
|
||||
window.win.webContents.on('ipc-message', proxyAuthResponseHandler);
|
||||
window.win?.webContents.on('ipc-message', proxyAuthResponseHandler);
|
||||
});
|
||||
|
||||
// Remember credentials for the session in case
|
||||
|
|
|
@ -181,9 +181,9 @@ class CodeMain {
|
|||
return [new InstantiationService(services, true), instanceEnvironment, environmentService, configurationService, stateService, bufferLogService];
|
||||
}
|
||||
|
||||
private patchEnvironment(environmentService: IEnvironmentMainService): IProcessEnvironment {
|
||||
private patchEnvironment(environmentMainService: IEnvironmentMainService): IProcessEnvironment {
|
||||
const instanceEnvironment: IProcessEnvironment = {
|
||||
VSCODE_IPC_HOOK: environmentService.mainIPCHandle
|
||||
VSCODE_IPC_HOOK: environmentMainService.mainIPCHandle
|
||||
};
|
||||
|
||||
['VSCODE_NLS_CONFIG', 'VSCODE_PORTABLE'].forEach(key => {
|
||||
|
@ -198,16 +198,16 @@ class CodeMain {
|
|||
return instanceEnvironment;
|
||||
}
|
||||
|
||||
private initServices(environmentService: IEnvironmentMainService, configurationService: ConfigurationService, stateService: StateService): Promise<unknown> {
|
||||
private initServices(environmentMainService: IEnvironmentMainService, configurationService: ConfigurationService, stateService: StateService): Promise<unknown> {
|
||||
|
||||
// Environment service (paths)
|
||||
const environmentServiceInitialization = Promise.all<void | undefined>([
|
||||
environmentService.extensionsPath,
|
||||
environmentService.nodeCachedDataDir,
|
||||
environmentService.logsPath,
|
||||
environmentService.globalStorageHome.fsPath,
|
||||
environmentService.workspaceStorageHome.fsPath,
|
||||
environmentService.backupHome
|
||||
environmentMainService.extensionsPath,
|
||||
environmentMainService.nodeCachedDataDir,
|
||||
environmentMainService.logsPath,
|
||||
environmentMainService.globalStorageHome.fsPath,
|
||||
environmentMainService.workspaceStorageHome.fsPath,
|
||||
environmentMainService.backupHome
|
||||
].map(path => path ? promises.mkdir(path, { recursive: true }) : undefined));
|
||||
|
||||
// Configuration service
|
||||
|
@ -219,14 +219,14 @@ class CodeMain {
|
|||
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
|
||||
}
|
||||
|
||||
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, retry: boolean): Promise<NodeIPCServer> {
|
||||
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, retry: boolean): Promise<NodeIPCServer> {
|
||||
|
||||
// Try to setup a server for running. If that succeeds it means
|
||||
// we are the first instance to startup. Otherwise it is likely
|
||||
// that another instance is already running.
|
||||
let mainProcessNodeIpcServer: NodeIPCServer;
|
||||
try {
|
||||
mainProcessNodeIpcServer = await nodeIPCServe(environmentService.mainIPCHandle);
|
||||
mainProcessNodeIpcServer = await nodeIPCServe(environmentMainService.mainIPCHandle);
|
||||
once(lifecycleMainService.onWillShutdown)(() => mainProcessNodeIpcServer.dispose());
|
||||
} catch (error) {
|
||||
|
||||
|
@ -235,7 +235,7 @@ class CodeMain {
|
|||
if (error.code !== 'EADDRINUSE') {
|
||||
|
||||
// Show a dialog for errors that can be resolved by the user
|
||||
this.handleStartupDataDirError(environmentService, error);
|
||||
this.handleStartupDataDirError(environmentMainService, error);
|
||||
|
||||
// Any other runtime error is just printed to the console
|
||||
throw error;
|
||||
|
@ -244,7 +244,7 @@ class CodeMain {
|
|||
// there's a running instance, let's connect to it
|
||||
let client: NodeIPCClient<string>;
|
||||
try {
|
||||
client = await nodeIPCConnect(environmentService.mainIPCHandle, 'main');
|
||||
client = await nodeIPCConnect(environmentMainService.mainIPCHandle, 'main');
|
||||
} catch (error) {
|
||||
|
||||
// Handle unexpected connection errors by showing a dialog to the user
|
||||
|
@ -263,18 +263,18 @@ class CodeMain {
|
|||
// let's delete it, since we can't connect to it and then
|
||||
// retry the whole thing
|
||||
try {
|
||||
unlinkSync(environmentService.mainIPCHandle);
|
||||
unlinkSync(environmentMainService.mainIPCHandle);
|
||||
} catch (error) {
|
||||
logService.warn('Could not delete obsolete instance handle', error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, false);
|
||||
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, false);
|
||||
}
|
||||
|
||||
// Tests from CLI require to be the only instance currently
|
||||
if (environmentService.extensionTestsLocationURI && !environmentService.debugExtensionHost.break) {
|
||||
if (environmentMainService.extensionTestsLocationURI && !environmentMainService.debugExtensionHost.break) {
|
||||
const msg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
|
||||
logService.error(msg);
|
||||
client.dispose();
|
||||
|
@ -344,9 +344,9 @@ class CodeMain {
|
|||
return mainProcessNodeIpcServer;
|
||||
}
|
||||
|
||||
private handleStartupDataDirError(environmentService: IEnvironmentMainService, error: NodeJS.ErrnoException): void {
|
||||
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, error: NodeJS.ErrnoException): void {
|
||||
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
||||
const directories = coalesce([environmentService.userDataPath, environmentService.extensionsPath, XDG_RUNTIME_DIR]).map(folder => getPathLabel(folder, environmentService));
|
||||
const directories = coalesce([environmentMainService.userDataPath, environmentMainService.extensionsPath, XDG_RUNTIME_DIR]).map(folder => getPathLabel(folder, environmentMainService));
|
||||
|
||||
this.showStartupWarningDialog(
|
||||
localize('startupDataDirError', "Unable to write program user data."),
|
||||
|
@ -369,9 +369,9 @@ class CodeMain {
|
|||
});
|
||||
}
|
||||
|
||||
private async windowsAllowSetForegroundWindow(launchService: ILaunchMainService, logService: ILogService): Promise<void> {
|
||||
private async windowsAllowSetForegroundWindow(launchMainService: ILaunchMainService, logService: ILogService): Promise<void> {
|
||||
if (isWindows) {
|
||||
const processId = await launchService.getMainProcessId();
|
||||
const processId = await launchMainService.getMainProcessId();
|
||||
|
||||
logService.trace('Sending some foreground love to the running instance:', processId);
|
||||
|
||||
|
|
|
@ -48,10 +48,10 @@ export class FileProtocolHandler extends Disposable {
|
|||
}
|
||||
|
||||
injectWindowsMainService(windowsMainService: IWindowsMainService): void {
|
||||
this._register(windowsMainService.onWindowReady(window => {
|
||||
this._register(windowsMainService.onDidSignalReadyWindow(window => {
|
||||
if (window.config?.extensionDevelopmentPath || window.config?.extensionTestsPath) {
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(Event.any(window.onClose, window.onDestroy)(() => disposables.dispose()));
|
||||
disposables.add(Event.any(window.onDidClose, window.onDidDestroy)(() => disposables.dispose()));
|
||||
|
||||
// Allow access to extension development path
|
||||
if (window.config.extensionDevelopmentPath) {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const bootstrapWindow = bootstrapWindowLib();
|
||||
|
||||
// Load issue reporter into window
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const bootstrapWindow = bootstrapWindowLib();
|
||||
|
||||
// Load process explorer into window
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
/// <reference path="../../../../typings/require.d.ts" />
|
||||
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const bootstrapWindow = bootstrapWindowLib();
|
||||
|
||||
// Add a perf entry right from the top
|
||||
|
@ -76,5 +76,4 @@
|
|||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
}());
|
||||
|
|
|
@ -118,6 +118,10 @@ class ModesContentComputer implements IHoverComputer<HoverPartInfo[]> {
|
|||
|
||||
const maxColumn = model.getLineMaxColumn(lineNumber);
|
||||
const lineDecorations = this._editor.getLineDecorations(lineNumber).filter((d) => {
|
||||
if (d.options.isWholeLine) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
|
||||
const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
|
||||
if (startColumn > hoverRange.startColumn || hoverRange.endColumn > endColumn) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import { Context as SuggestContext, CompletionItem } from './suggest';
|
|||
import { CompletionModel } from './completionModel';
|
||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService, IColorTheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { registerColor, editorWidgetBackground, listFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerColor, editorWidgetBackground, quickInputListFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { TimeoutTimer, CancelablePromise, createCancelablePromise, disposableTimeout } from 'vs/base/common/async';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -40,7 +40,7 @@ import { clamp } from 'vs/base/common/numbers';
|
|||
export const editorSuggestWidgetBackground = registerColor('editorSuggestWidget.background', { dark: editorWidgetBackground, light: editorWidgetBackground, hc: editorWidgetBackground }, nls.localize('editorSuggestWidgetBackground', 'Background color of the suggest widget.'));
|
||||
export const editorSuggestWidgetBorder = registerColor('editorSuggestWidget.border', { dark: editorWidgetBorder, light: editorWidgetBorder, hc: editorWidgetBorder }, nls.localize('editorSuggestWidgetBorder', 'Border color of the suggest widget.'));
|
||||
export const editorSuggestWidgetForeground = registerColor('editorSuggestWidget.foreground', { dark: editorForeground, light: editorForeground, hc: editorForeground }, nls.localize('editorSuggestWidgetForeground', 'Foreground color of the suggest widget.'));
|
||||
export const editorSuggestWidgetSelectedBackground = registerColor('editorSuggestWidget.selectedBackground', { dark: listFocusBackground, light: listFocusBackground, hc: listFocusBackground }, nls.localize('editorSuggestWidgetSelectedBackground', 'Background color of the selected entry in the suggest widget.'));
|
||||
export const editorSuggestWidgetSelectedBackground = registerColor('editorSuggestWidget.selectedBackground', { dark: quickInputListFocusBackground, light: quickInputListFocusBackground, hc: quickInputListFocusBackground }, nls.localize('editorSuggestWidgetSelectedBackground', 'Background color of the selected entry in the suggest widget.'));
|
||||
export const editorSuggestWidgetHighlightForeground = registerColor('editorSuggestWidget.highlightForeground', { dark: listHighlightForeground, light: listHighlightForeground, hc: listHighlightForeground }, nls.localize('editorSuggestWidgetHighlightForeground', 'Color of the match highlights in the suggest widget.'));
|
||||
|
||||
const enum State {
|
||||
|
|
|
@ -52,7 +52,7 @@ class TestGlobalStyleSheet extends GlobalStyleSheet {
|
|||
|
||||
suite('Decoration Render Options', () => {
|
||||
let options: IDecorationRenderOptions = {
|
||||
gutterIconPath: URI.parse('https://github.com/microsoft/vscode/blob/master/resources/linux/code.png'),
|
||||
gutterIconPath: URI.parse('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png'),
|
||||
gutterIconSize: 'contain',
|
||||
backgroundColor: 'red',
|
||||
borderColor: 'yellow'
|
||||
|
@ -79,7 +79,7 @@ suite('Decoration Render Options', () => {
|
|||
const s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet);
|
||||
s.registerDecorationType('example', options);
|
||||
const sheet = readStyleSheet(styleSheet);
|
||||
assert(sheet.indexOf(`{background:url('https://github.com/microsoft/vscode/blob/master/resources/linux/code.png') center center no-repeat;background-size:contain;}`) >= 0);
|
||||
assert(sheet.indexOf(`{background:url('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png') center center no-repeat;background-size:contain;}`) >= 0);
|
||||
assert(sheet.indexOf(`{background-color:red;border-color:yellow;box-sizing: border-box;}`) >= 0);
|
||||
});
|
||||
|
||||
|
|
|
@ -321,34 +321,30 @@ export class ExecuteCommandAction extends Action {
|
|||
|
||||
export class SubmenuItemAction extends SubmenuAction {
|
||||
|
||||
readonly item: ISubmenuItem;
|
||||
|
||||
constructor(
|
||||
item: ISubmenuItem,
|
||||
menuService: IMenuService,
|
||||
contextKeyService: IContextKeyService,
|
||||
options?: IMenuActionOptions
|
||||
readonly item: ISubmenuItem,
|
||||
private readonly _menuService: IMenuService,
|
||||
private readonly _contextKeyService: IContextKeyService,
|
||||
private readonly _options?: IMenuActionOptions
|
||||
) {
|
||||
super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, [], 'submenu');
|
||||
}
|
||||
|
||||
get actions(): readonly IAction[] {
|
||||
const result: IAction[] = [];
|
||||
const menu = menuService.createMenu(item.submenu, contextKeyService);
|
||||
const groups = menu.getActions(options);
|
||||
const menu = this._menuService.createMenu(this.item.submenu, this._contextKeyService);
|
||||
const groups = menu.getActions(this._options);
|
||||
menu.dispose();
|
||||
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
|
||||
for (const [, actions] of groups) {
|
||||
if (actions.length > 0) {
|
||||
result.push(...actions);
|
||||
result.push(new Separator());
|
||||
}
|
||||
}
|
||||
|
||||
if (result.length) {
|
||||
result.pop(); // remove last separator
|
||||
}
|
||||
|
||||
super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, result, 'submenu');
|
||||
this.item = item;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,12 +38,12 @@ export class BackupMainService implements IBackupMainService {
|
|||
private readonly backupPathComparer = { isEqual: (pathA: string, pathB: string) => isEqual(pathA, pathB, !isLinux) };
|
||||
|
||||
constructor(
|
||||
@IEnvironmentMainService environmentService: IEnvironmentMainService,
|
||||
@IEnvironmentMainService environmentMainService: IEnvironmentMainService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
this.backupHome = environmentService.backupHome;
|
||||
this.workspacesJsonPath = environmentService.backupWorkspacesPath;
|
||||
this.backupHome = environmentMainService.backupHome;
|
||||
this.workspacesJsonPath = environmentMainService.backupWorkspacesPath;
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
|
|
|
@ -43,7 +43,12 @@ export class ElectronExtensionHostDebugBroadcastChannel<TContext> extends Extens
|
|||
return {};
|
||||
}
|
||||
|
||||
const debug = codeWindow.win.webContents.debugger;
|
||||
const win = codeWindow.win;
|
||||
if (!win) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const debug = win.webContents.debugger;
|
||||
|
||||
let listeners = debug.isAttached() ? Infinity : 0;
|
||||
const server = createServer(listener => {
|
||||
|
@ -61,7 +66,7 @@ export class ElectronExtensionHostDebugBroadcastChannel<TContext> extends Extens
|
|||
const onMessage = (_event: Event, method: string, params: unknown, sessionId?: string) =>
|
||||
writeMessage(({ method, params, sessionId }));
|
||||
|
||||
codeWindow.win.on('close', () => {
|
||||
win.on('close', () => {
|
||||
debug.removeListener('message', onMessage);
|
||||
listener.end();
|
||||
closed = true;
|
||||
|
@ -103,7 +108,7 @@ export class ElectronExtensionHostDebugBroadcastChannel<TContext> extends Extens
|
|||
});
|
||||
|
||||
await new Promise<void>(r => server.listen(0, r));
|
||||
codeWindow.win.on('close', () => server.close());
|
||||
win.on('close', () => server.close());
|
||||
|
||||
return { rendererDebugPort: (server.address() as AddressInfo).port };
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ export class Driver implements IDriver, IWindowDriverRegistry {
|
|||
await this.whenUnfrozen(windowId);
|
||||
|
||||
const window = this.windowsMainService.getWindowById(windowId);
|
||||
if (!window) {
|
||||
if (!window?.win) {
|
||||
throw new Error('Invalid window');
|
||||
}
|
||||
const webContents = window.win.webContents;
|
||||
|
@ -101,7 +101,7 @@ export class Driver implements IDriver, IWindowDriverRegistry {
|
|||
}
|
||||
|
||||
const window = this.windowsMainService.getWindowById(windowId);
|
||||
if (!window) {
|
||||
if (!window?.win) {
|
||||
throw new Error('Invalid window');
|
||||
}
|
||||
const webContents = window.win.webContents;
|
||||
|
@ -207,10 +207,10 @@ export class Driver implements IDriver, IWindowDriverRegistry {
|
|||
export async function serve(
|
||||
windowServer: IPCServer,
|
||||
handle: string,
|
||||
environmentService: IEnvironmentMainService,
|
||||
environmentMainService: IEnvironmentMainService,
|
||||
instantiationService: IInstantiationService
|
||||
): Promise<IDisposable> {
|
||||
const verbose = environmentService.driverVerbose;
|
||||
const verbose = environmentMainService.driverVerbose;
|
||||
const driver = instantiationService.createInstance(Driver, windowServer, { verbose });
|
||||
|
||||
const windowDriverRegistryChannel = new WindowDriverRegistryChannel(driver);
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as os from 'os';
|
||||
import { homedir, tmpdir } from 'os';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IDebugParams, IExtensionHostDebugParams, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import * as paths from 'vs/base/node/paths';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { getDefaultUserDataPath } from 'vs/base/node/userDataPath';
|
||||
import { dirname, join, normalize, resolve } from 'vs/base/common/path';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { FileAccess } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
@ -22,46 +22,46 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
get args(): NativeParsedArgs { return this._args; }
|
||||
|
||||
@memoize
|
||||
get appRoot(): string { return path.dirname(FileAccess.asFileUri('', require).fsPath); }
|
||||
get appRoot(): string { return dirname(FileAccess.asFileUri('', require).fsPath); }
|
||||
|
||||
readonly logsPath: string;
|
||||
|
||||
@memoize
|
||||
get userHome(): URI { return URI.file(os.homedir()); }
|
||||
get userHome(): URI { return URI.file(homedir()); }
|
||||
|
||||
@memoize
|
||||
get userDataPath(): string {
|
||||
const vscodePortable = process.env['VSCODE_PORTABLE'];
|
||||
if (vscodePortable) {
|
||||
return path.join(vscodePortable, 'user-data');
|
||||
return join(vscodePortable, 'user-data');
|
||||
}
|
||||
|
||||
return parseUserDataDir(this._args, process);
|
||||
}
|
||||
|
||||
@memoize
|
||||
get appSettingsHome(): URI { return URI.file(path.join(this.userDataPath, 'User')); }
|
||||
get appSettingsHome(): URI { return URI.file(join(this.userDataPath, 'User')); }
|
||||
|
||||
@memoize
|
||||
get tmpDir(): URI { return URI.file(os.tmpdir()); }
|
||||
get tmpDir(): URI { return URI.file(tmpdir()); }
|
||||
|
||||
@memoize
|
||||
get userRoamingDataHome(): URI { return this.appSettingsHome; }
|
||||
|
||||
@memoize
|
||||
get settingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||
get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||
|
||||
@memoize
|
||||
get userDataSyncHome(): URI { return resources.joinPath(this.userRoamingDataHome, 'sync'); }
|
||||
get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync'); }
|
||||
|
||||
@memoize
|
||||
get userDataSyncLogResource(): URI { return URI.file(path.join(this.logsPath, 'userDataSync.log')); }
|
||||
get userDataSyncLogResource(): URI { return URI.file(join(this.logsPath, 'userDataSync.log')); }
|
||||
|
||||
@memoize
|
||||
get sync(): 'on' | 'off' | undefined { return this.args.sync; }
|
||||
|
||||
@memoize
|
||||
get machineSettingsResource(): URI { return resources.joinPath(URI.file(path.join(this.userDataPath, 'Machine')), 'settings.json'); }
|
||||
get machineSettingsResource(): URI { return joinPath(URI.file(join(this.userDataPath, 'Machine')), 'settings.json'); }
|
||||
|
||||
@memoize
|
||||
get globalStorageHome(): URI { return URI.joinPath(this.appSettingsHome, 'globalStorage'); }
|
||||
|
@ -70,32 +70,32 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
get workspaceStorageHome(): URI { return URI.joinPath(this.appSettingsHome, 'workspaceStorage'); }
|
||||
|
||||
@memoize
|
||||
get keybindingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'keybindings.json'); }
|
||||
get keybindingsResource(): URI { return joinPath(this.userRoamingDataHome, 'keybindings.json'); }
|
||||
|
||||
@memoize
|
||||
get keyboardLayoutResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }
|
||||
get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); }
|
||||
|
||||
@memoize
|
||||
get argvResource(): URI {
|
||||
const vscodePortable = process.env['VSCODE_PORTABLE'];
|
||||
if (vscodePortable) {
|
||||
return URI.file(path.join(vscodePortable, 'argv.json'));
|
||||
return URI.file(join(vscodePortable, 'argv.json'));
|
||||
}
|
||||
|
||||
return resources.joinPath(this.userHome, product.dataFolderName, 'argv.json');
|
||||
return joinPath(this.userHome, product.dataFolderName, 'argv.json');
|
||||
}
|
||||
|
||||
@memoize
|
||||
get snippetsHome(): URI { return resources.joinPath(this.userRoamingDataHome, 'snippets'); }
|
||||
get snippetsHome(): URI { return joinPath(this.userRoamingDataHome, 'snippets'); }
|
||||
|
||||
@memoize
|
||||
get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; }
|
||||
|
||||
@memoize
|
||||
get untitledWorkspacesHome(): URI { return URI.file(path.join(this.userDataPath, 'Workspaces')); }
|
||||
get untitledWorkspacesHome(): URI { return URI.file(join(this.userDataPath, 'Workspaces')); }
|
||||
|
||||
@memoize
|
||||
get installSourcePath(): string { return path.join(this.userDataPath, 'installSource'); }
|
||||
get installSourcePath(): string { return join(this.userDataPath, 'installSource'); }
|
||||
|
||||
@memoize
|
||||
get builtinExtensionsPath(): string {
|
||||
|
@ -103,7 +103,7 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
if (fromArgs) {
|
||||
return fromArgs;
|
||||
} else {
|
||||
return path.normalize(path.join(FileAccess.asFileUri('', require).fsPath, '..', 'extensions'));
|
||||
return normalize(join(FileAccess.asFileUri('', require).fsPath, '..', 'extensions'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
if (fromArgs) {
|
||||
return fromArgs;
|
||||
} else {
|
||||
return path.join(this.userDataPath, 'CachedExtensionVSIXs');
|
||||
return join(this.userDataPath, 'CachedExtensionVSIXs');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,10 +131,10 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
|
||||
const vscodePortable = process.env['VSCODE_PORTABLE'];
|
||||
if (vscodePortable) {
|
||||
return path.join(vscodePortable, 'extensions');
|
||||
return join(vscodePortable, 'extensions');
|
||||
}
|
||||
|
||||
return resources.joinPath(this.userHome, product.dataFolderName, 'extensions').fsPath;
|
||||
return joinPath(this.userHome, product.dataFolderName, 'extensions').fsPath;
|
||||
}
|
||||
|
||||
@memoize
|
||||
|
@ -145,7 +145,7 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
if (/^[^:/?#]+?:\/\//.test(p)) {
|
||||
return URI.parse(p);
|
||||
}
|
||||
return URI.file(path.normalize(p));
|
||||
return URI.file(normalize(p));
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
|
@ -158,7 +158,7 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
if (/^[^:/?#]+?:\/\//.test(s)) {
|
||||
return URI.parse(s);
|
||||
}
|
||||
return URI.file(path.normalize(s));
|
||||
return URI.file(normalize(s));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
get logLevel(): string | undefined { return this._args.log; }
|
||||
|
||||
@memoize
|
||||
get serviceMachineIdResource(): URI { return resources.joinPath(URI.file(this.userDataPath), 'machineid'); }
|
||||
get serviceMachineIdResource(): URI { return joinPath(URI.file(this.userDataPath), 'machineid'); }
|
||||
|
||||
get crashReporterId(): string | undefined { return this._args['crash-reporter-id']; }
|
||||
get crashReporterDirectory(): string | undefined { return this._args['crash-reporter-directory']; }
|
||||
|
@ -196,13 +196,13 @@ export class NativeEnvironmentService implements INativeEnvironmentService {
|
|||
get driverHandle(): string | undefined { return this._args['driver']; }
|
||||
|
||||
@memoize
|
||||
get telemetryLogResource(): URI { return URI.file(path.join(this.logsPath, 'telemetry.log')); }
|
||||
get telemetryLogResource(): URI { return URI.file(join(this.logsPath, 'telemetry.log')); }
|
||||
get disableTelemetry(): boolean { return !!this._args['disable-telemetry']; }
|
||||
|
||||
constructor(protected _args: NativeParsedArgs) {
|
||||
if (!_args.logsPath) {
|
||||
const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');
|
||||
_args.logsPath = path.join(this.userDataPath, 'logs', key);
|
||||
_args.logsPath = join(this.userDataPath, 'logs', key);
|
||||
}
|
||||
this.logsPath = _args.logsPath;
|
||||
}
|
||||
|
@ -231,15 +231,15 @@ export function parsePathArg(arg: string | undefined, process: NodeJS.Process):
|
|||
|
||||
// Determine if the arg is relative or absolute, if relative use the original CWD
|
||||
// (VSCODE_CWD), not the potentially overridden one (process.cwd()).
|
||||
const resolved = path.resolve(arg);
|
||||
const resolved = resolve(arg);
|
||||
|
||||
if (path.normalize(arg) === resolved) {
|
||||
if (normalize(arg) === resolved) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
return path.resolve(process.env['VSCODE_CWD'] || process.cwd(), arg);
|
||||
return resolve(process.env['VSCODE_CWD'] || process.cwd(), arg);
|
||||
}
|
||||
|
||||
export function parseUserDataDir(args: NativeParsedArgs, process: NodeJS.Process): string {
|
||||
return parsePathArg(args['user-data-dir'], process) || path.resolve(paths.getDefaultUserDataPath());
|
||||
return parsePathArg(args['user-data-dir'], process) || resolve(getDefaultUserDataPath());
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ export class IssueMainService implements ICommonIssueService {
|
|||
constructor(
|
||||
private machineId: string,
|
||||
private userEnv: IProcessEnvironment,
|
||||
@IEnvironmentMainService private readonly environmentService: IEnvironmentMainService,
|
||||
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
|
||||
@ILaunchMainService private readonly launchMainService: ILaunchMainService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IDiagnosticsService private readonly diagnosticsService: IDiagnosticsService,
|
||||
|
@ -271,7 +271,7 @@ export class IssueMainService implements ICommonIssueService {
|
|||
this._processExplorerWindow.setMenuBarVisibility(false);
|
||||
|
||||
const windowConfiguration = {
|
||||
appRoot: this.environmentService.appRoot,
|
||||
appRoot: this.environmentMainService.appRoot,
|
||||
windowId: this._processExplorerWindow.id,
|
||||
userEnv: this.userEnv,
|
||||
machineId: this.machineId,
|
||||
|
@ -397,13 +397,13 @@ export class IssueMainService implements ICommonIssueService {
|
|||
}
|
||||
|
||||
const windowConfiguration = {
|
||||
appRoot: this.environmentService.appRoot,
|
||||
appRoot: this.environmentMainService.appRoot,
|
||||
windowId: this._issueWindow.id,
|
||||
machineId: this.machineId,
|
||||
userEnv: this.userEnv,
|
||||
data,
|
||||
features,
|
||||
disableExtensions: this.environmentService.disableExtensions,
|
||||
disableExtensions: this.environmentMainService.disableExtensions,
|
||||
os: {
|
||||
type: os.type(),
|
||||
arch: os.arch(),
|
||||
|
|
|
@ -21,6 +21,7 @@ import { IMainProcessInfo, IWindowInfo } from 'vs/platform/launch/common/launch'
|
|||
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
|
||||
export const ID = 'launchMainService';
|
||||
export const ILaunchMainService = createDecorator<ILaunchMainService>(ID);
|
||||
|
@ -293,8 +294,9 @@ export class LaunchMainService implements ILaunchMainService {
|
|||
|
||||
private codeWindowToInfo(window: ICodeWindow): IWindowInfo {
|
||||
const folderURIs = this.getFolderURIs(window);
|
||||
const win = assertIsDefined(window.win);
|
||||
|
||||
return this.browserWindowToInfo(window.win, folderURIs, window.remoteAuthority);
|
||||
return this.browserWindowToInfo(win, folderURIs, window.remoteAuthority);
|
||||
}
|
||||
|
||||
private browserWindowToInfo(window: BrowserWindow, folderURIs: URI[] = [], remoteAuthority?: string): IWindowInfo {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue