mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge branch 'main' into fix-156481
This commit is contained in:
@@ -259,6 +259,7 @@
|
||||
"windows-process-tree",
|
||||
"worker_threads",
|
||||
"xterm",
|
||||
"xterm-addon-canvas",
|
||||
"xterm-addon-search",
|
||||
"xterm-addon-serialize",
|
||||
"xterm-addon-unicode11",
|
||||
|
||||
@@ -197,10 +197,10 @@
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "~needs version info",
|
||||
"name": "~version-info-needed",
|
||||
"action": "updateLabels",
|
||||
"addLabel": "info-needed",
|
||||
"removeLabel": "~needs version info",
|
||||
"removeLabel": "~version-info-needed",
|
||||
"comment": "Thanks for creating this issue! We figured it's missing some basic information, such as a version number, or in some other way doesn't follow our [issue reporting guidelines](https://aka.ms/vscodeissuereporting). Please take the time to review these and update the issue.\n\nHappy Coding!"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -39,8 +39,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
@@ -92,8 +91,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
@@ -155,8 +153,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
||||
@@ -125,8 +125,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
@@ -197,8 +196,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesMacOS-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
@@ -271,8 +269,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules22-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules22-
|
||||
key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }}
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"July 2022\""
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"August 2022\""
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
disturl "https://electronjs.org/headers"
|
||||
target "18.3.5"
|
||||
target "19.0.11"
|
||||
runtime "electron"
|
||||
build_from_source "true"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2022-07-12T09:44:15.185Z
|
||||
2022-08-01T11:24:47.411Z
|
||||
|
||||
@@ -20,6 +20,9 @@ vscode-textmate/webpack.config.js
|
||||
|
||||
xterm/src/**
|
||||
|
||||
xterm-addon-canvas/src/**
|
||||
xterm-addon-canvas/out/**
|
||||
|
||||
xterm-addon-search/src/**
|
||||
xterm-addon-search/out/**
|
||||
xterm-addon-search/fixtures/**
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const crypto = require("crypto");
|
||||
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
|
||||
const shasum = crypto.createHash('sha1');
|
||||
for (const ext of productjson.builtInExtensions) {
|
||||
shasum.update(`${ext.name}@${ext.version}`);
|
||||
}
|
||||
process.stdout.write(shasum.digest('hex'));
|
||||
@@ -0,0 +1,17 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
|
||||
const shasum = crypto.createHash('sha1');
|
||||
|
||||
for (const ext of productjson.builtInExtensions) {
|
||||
shasum.update(`${ext.name}@${ext.version}`);
|
||||
}
|
||||
|
||||
process.stdout.write(shasum.digest('hex'));
|
||||
@@ -38,6 +38,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js x64 $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -47,6 +48,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -88,6 +95,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -38,6 +38,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js x64 $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -47,6 +48,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -88,6 +95,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -72,6 +72,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -81,6 +82,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -115,6 +122,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -58,6 +58,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js "alpine" $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -67,6 +68,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -98,6 +105,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -91,14 +91,30 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "genericNodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -178,6 +194,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- script: |
|
||||
set -e
|
||||
|
||||
@@ -10,6 +10,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -19,6 +20,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -50,6 +57,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -22,174 +22,168 @@ variables:
|
||||
- name: VSCODE_STEP_ON_IT
|
||||
value: false
|
||||
|
||||
stages:
|
||||
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- stage: MaintainNodeModulesCache
|
||||
displayName: Maintain node_modules cache
|
||||
jobs:
|
||||
- job: MaintainNodeModulesCache
|
||||
displayName: Maintain node_modules cache
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
steps:
|
||||
- template: product-build-pr-cache.yml
|
||||
|
||||
jobs:
|
||||
- ${{ if ne(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- stage: Compile
|
||||
- job: Compile
|
||||
displayName: Compile & Hygiene
|
||||
jobs:
|
||||
- job: Compile
|
||||
displayName: Compile & Hygiene
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-compile.yml
|
||||
parameters:
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-compile.yml
|
||||
parameters:
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
|
||||
- stage: Test
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: Linuxx64UnitTest
|
||||
displayName: Linux (Unit Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: true
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
- job: Linuxx64IntegrationTest
|
||||
displayName: Linux (Integration Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
- job: Linuxx64SmokeTest
|
||||
displayName: Linux (Smoke Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64UnitTest
|
||||
displayName: Linux (Unit Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: true
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
|
||||
# - job: macOSUnitTest
|
||||
# displayName: macOS (Unit Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSIntegrationTest
|
||||
# displayName: macOS (Integration Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSSmokeTest
|
||||
# displayName: macOS (Smoke Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64IntegrationTest
|
||||
displayName: Linux (Integration Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
|
||||
# - job: WindowsUnitTests
|
||||
# displayName: Windows (Unit Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsIntegrationTests
|
||||
# displayName: Windows (Integration Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsSmokeTests
|
||||
# displayName: Windows (Smoke Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64SmokeTest
|
||||
displayName: Linux (Smoke Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
||||
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- job: Linuxx64MaintainNodeModulesCache
|
||||
displayName: Linux (Maintain node_modules cache)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-build-pr-cache.yml
|
||||
|
||||
# - job: macOSUnitTest
|
||||
# displayName: macOS (Unit Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSIntegrationTest
|
||||
# displayName: macOS (Integration Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSSmokeTest
|
||||
# displayName: macOS (Smoke Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
||||
# - job: WindowsUnitTests
|
||||
# displayName: Windows (Unit Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsIntegrationTests
|
||||
# displayName: Windows (Integration Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsSmokeTests
|
||||
# displayName: Windows (Smoke Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
||||
@@ -46,6 +46,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
# using `genericNodeModules` instead of `nodeModules` here to avoid sharing the cache with builds running inside containers
|
||||
@@ -56,6 +57,13 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
# Cache built-in extensions to avoid GH rate limits.
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -94,6 +102,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -49,6 +49,7 @@ steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js "web" $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -58,6 +59,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf .build/node_modules_cache/cache.tgz
|
||||
@@ -89,6 +96,13 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/lib/builtInExtensions.js
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt
|
||||
|
||||
@@ -36,8 +36,8 @@ steps:
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { node test/unit/browser/index.js --sequential --browser chromium --browser firefox --tfs "Browser Unit Tests" }
|
||||
displayName: Run unit tests (Browser, Chromium & Firefox)
|
||||
exec { node test/unit/browser/index.js --sequential --browser chromium --tfs "Browser Unit Tests" }
|
||||
displayName: Run unit tests (Browser, Chromium)
|
||||
timeoutInMinutes: 20
|
||||
|
||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
@@ -59,8 +59,8 @@ steps:
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { yarn test-browser-no-install --sequential --build --browser chromium --browser firefox --tfs "Browser Unit Tests" }
|
||||
displayName: Run unit tests (Browser, Chromium & Firefox)
|
||||
exec { yarn test-browser-no-install --sequential --build --browser chromium --tfs "Browser Unit Tests" }
|
||||
displayName: Run unit tests (Browser, Chromium)
|
||||
timeoutInMinutes: 20
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
|
||||
|
||||
@@ -80,6 +80,7 @@ steps:
|
||||
"$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch
|
||||
"$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin
|
||||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js > .build/yarnlockhash
|
||||
node build/azure-pipelines/common/computeBuiltInDepsCacheKey.js > .build/builtindepshash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
@@ -89,6 +90,12 @@ steps:
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"builtInDeps" | .build/builtindepshash'
|
||||
path: .build/builtInExtensions
|
||||
displayName: Restore built-in extensions
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -119,6 +126,14 @@ steps:
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { node build/lib/builtInExtensions.js }
|
||||
env:
|
||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Download missing built-in extensions
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
@@ -236,8 +236,8 @@ exports.compileExtensionMediaBuildTask = compileExtensionMediaBuildTask;
|
||||
const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions'));
|
||||
const compileExtensionsBuildTask = task.define('compile-extensions-build', task.series(
|
||||
cleanExtensionsBuildTask,
|
||||
task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream(false).pipe(gulp.dest('.build'))),
|
||||
task.define('bundle-extensions-build', () => ext.packageLocalExtensionsStream(false).pipe(gulp.dest('.build'))),
|
||||
task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream(false, product.extensionsGallery?.serviceUrl).pipe(gulp.dest('.build'))),
|
||||
));
|
||||
|
||||
gulp.task(compileExtensionsBuildTask);
|
||||
|
||||
@@ -229,7 +229,7 @@ function packageTask(sourceFolderName, destinationFolderName) {
|
||||
const compileWebExtensionsBuildTask = task.define('compile-web-extensions-build', task.series(
|
||||
task.define('clean-web-extensions-build', util.rimraf('.build/web/extensions')),
|
||||
task.define('bundle-web-extensions-build', () => extensions.packageLocalExtensionsStream(true).pipe(gulp.dest('.build/web'))),
|
||||
task.define('bundle-marketplace-web-extensions-build', () => extensions.packageMarketplaceExtensionsStream(true, product.extensionsGallery?.serviceUrl).pipe(gulp.dest('.build/web'))),
|
||||
task.define('bundle-marketplace-web-extensions-build', () => extensions.packageMarketplaceExtensionsStream(true).pipe(gulp.dest('.build/web'))),
|
||||
task.define('bundle-web-extension-media-build', () => extensions.buildExtensionMedia(false, '.build/web/extensions')),
|
||||
));
|
||||
gulp.task(compileWebExtensionsBuildTask);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getBuiltInExtensions = void 0;
|
||||
exports.getBuiltInExtensions = exports.getExtensionStream = void 0;
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
@@ -44,6 +44,21 @@ function isUpToDate(extension) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function getExtensionDownloadStream(extension) {
|
||||
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
|
||||
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
|
||||
}
|
||||
function getExtensionStream(extension) {
|
||||
// if the extension exists on disk, use those files instead of downloading anew
|
||||
if (isUpToDate(extension)) {
|
||||
log('[extensions]', `${extension.name}@${extension.version} up to date`, ansiColors.green('✔︎'));
|
||||
return vfs.src(['**'], { cwd: getExtensionPath(extension), dot: true })
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
|
||||
}
|
||||
return getExtensionDownloadStream(extension);
|
||||
}
|
||||
exports.getExtensionStream = getExtensionStream;
|
||||
function syncMarketplaceExtension(extension) {
|
||||
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
|
||||
const source = ansiColors.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
|
||||
@@ -52,8 +67,7 @@ function syncMarketplaceExtension(extension) {
|
||||
return es.readArray([]);
|
||||
}
|
||||
rimraf.sync(getExtensionPath(extension));
|
||||
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
|
||||
return getExtensionDownloadStream(extension)
|
||||
.pipe(vfs.dest('.build/builtInExtensions'))
|
||||
.on('end', () => log(source, extension.name, ansiColors.green('✔︎')));
|
||||
}
|
||||
|
||||
@@ -68,10 +68,26 @@ function isUpToDate(extension: IExtensionDefinition): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
function getExtensionDownloadStream(extension: IExtensionDefinition) {
|
||||
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
|
||||
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
|
||||
}
|
||||
|
||||
export function getExtensionStream(extension: IExtensionDefinition) {
|
||||
// if the extension exists on disk, use those files instead of downloading anew
|
||||
if (isUpToDate(extension)) {
|
||||
log('[extensions]', `${extension.name}@${extension.version} up to date`, ansiColors.green('✔︎'));
|
||||
return vfs.src(['**'], { cwd: getExtensionPath(extension), dot: true })
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`));
|
||||
}
|
||||
|
||||
return getExtensionDownloadStream(extension);
|
||||
}
|
||||
|
||||
function syncMarketplaceExtension(extension: IExtensionDefinition): Stream {
|
||||
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
|
||||
const source = ansiColors.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
|
||||
|
||||
if (isUpToDate(extension)) {
|
||||
log(source, `${extension.name}@${extension.version}`, ansiColors.green('✔︎'));
|
||||
return es.readArray([]);
|
||||
@@ -79,8 +95,7 @@ function syncMarketplaceExtension(extension: IExtensionDefinition): Stream {
|
||||
|
||||
rimraf.sync(getExtensionPath(extension));
|
||||
|
||||
return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
|
||||
return getExtensionDownloadStream(extension)
|
||||
.pipe(vfs.dest('.build/builtInExtensions'))
|
||||
.on('end', () => log(source, extension.name, ansiColors.green('✔︎')));
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const buffer = require('gulp-buffer');
|
||||
const jsoncParser = require("jsonc-parser");
|
||||
const dependencies_1 = require("./dependencies");
|
||||
const _ = require("underscore");
|
||||
const builtInExtensions_1 = require("./builtInExtensions");
|
||||
const util = require('./util');
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const commit = util.getVersion(root);
|
||||
@@ -312,16 +313,15 @@ function packageLocalExtensionsStream(forWeb) {
|
||||
.pipe(util2.setExecutableBit(['**/*.sh'])));
|
||||
}
|
||||
exports.packageLocalExtensionsStream = packageLocalExtensionsStream;
|
||||
function packageMarketplaceExtensionsStream(forWeb, galleryServiceUrl) {
|
||||
function packageMarketplaceExtensionsStream(forWeb) {
|
||||
const marketplaceExtensionsDescriptions = [
|
||||
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
|
||||
...(forWeb ? webBuiltInExtensions : [])
|
||||
];
|
||||
const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions
|
||||
.map(extension => {
|
||||
const input = (galleryServiceUrl ? fromMarketplace(galleryServiceUrl, extension) : fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||
return updateExtensionPackageJSON(input, (data) => {
|
||||
const src = (0, builtInExtensions_1.getExtensionStream)(extension).pipe(rename(p => p.dirname = `extensions/${p.dirname}`));
|
||||
return updateExtensionPackageJSON(src, (data) => {
|
||||
delete data.scripts;
|
||||
delete data.dependencies;
|
||||
delete data.devDependencies;
|
||||
@@ -399,6 +399,7 @@ const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
'ipynb/esbuild.js',
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import * as jsoncParser from 'jsonc-parser';
|
||||
import webpack = require('webpack');
|
||||
import { getProductionDependencies } from './dependencies';
|
||||
import _ = require('underscore');
|
||||
import { getExtensionStream } from './builtInExtensions';
|
||||
const util = require('./util');
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const commit = util.getVersion(root);
|
||||
@@ -381,7 +382,7 @@ export function packageLocalExtensionsStream(forWeb: boolean): Stream {
|
||||
);
|
||||
}
|
||||
|
||||
export function packageMarketplaceExtensionsStream(forWeb: boolean, galleryServiceUrl?: string): Stream {
|
||||
export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
|
||||
const marketplaceExtensionsDescriptions = [
|
||||
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
|
||||
...(forWeb ? webBuiltInExtensions : [])
|
||||
@@ -390,9 +391,8 @@ export function packageMarketplaceExtensionsStream(forWeb: boolean, galleryServi
|
||||
es.merge(
|
||||
...marketplaceExtensionsDescriptions
|
||||
.map(extension => {
|
||||
const input = (galleryServiceUrl ? fromMarketplace(galleryServiceUrl, extension) : fromGithub(extension))
|
||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||
return updateExtensionPackageJSON(input, (data: any) => {
|
||||
const src = getExtensionStream(extension).pipe(rename(p => p.dirname = `extensions/${p.dirname}`));
|
||||
return updateExtensionPackageJSON(src, (data: any) => {
|
||||
delete data.scripts;
|
||||
delete data.dependencies;
|
||||
delete data.devDependencies;
|
||||
@@ -486,6 +486,7 @@ const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
'ipynb/esbuild.js',
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ const CORE_TYPES = [
|
||||
'BigInt64Array',
|
||||
'btoa',
|
||||
'atob',
|
||||
'AbortController',
|
||||
'AbortSignal',
|
||||
'MessageChannel',
|
||||
'MessagePort',
|
||||
|
||||
@@ -52,6 +52,7 @@ const CORE_TYPES = [
|
||||
'BigInt64Array',
|
||||
'btoa',
|
||||
'atob',
|
||||
'AbortController',
|
||||
'AbortSignal',
|
||||
'MessageChannel',
|
||||
'MessagePort',
|
||||
|
||||
+14
-2
@@ -438,8 +438,20 @@ async function getNLS(resourceUrlTemplate, languageId, version) {
|
||||
}
|
||||
catch (err) {
|
||||
if (/\[404\]/.test(err.message)) {
|
||||
console.warn(`Language pack ${languageId}@${version} is missing. Downloading previous version...`);
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, previousVersion(version));
|
||||
const thePreviousVersion = previousVersion(version);
|
||||
console.warn(`Language pack ${languageId}@${version} is missing. Downloading previous version ${thePreviousVersion}...`);
|
||||
try {
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, thePreviousVersion);
|
||||
}
|
||||
catch (err) {
|
||||
if (/\[404\]/.test(err.message)) {
|
||||
console.warn(`Language pack ${languageId}@${thePreviousVersion} is missing. Downloading previous version...`);
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, previousVersion(thePreviousVersion));
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
|
||||
+12
-2
@@ -622,8 +622,18 @@ async function getNLS(resourceUrlTemplate: string, languageId: string, version:
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, version);
|
||||
} catch (err) {
|
||||
if (/\[404\]/.test(err.message)) {
|
||||
console.warn(`Language pack ${languageId}@${version} is missing. Downloading previous version...`);
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, previousVersion(version));
|
||||
const thePreviousVersion = previousVersion(version);
|
||||
console.warn(`Language pack ${languageId}@${version} is missing. Downloading previous version ${thePreviousVersion}...`);
|
||||
try {
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, thePreviousVersion);
|
||||
} catch (err) {
|
||||
if (/\[404\]/.test(err.message)) {
|
||||
console.warn(`Language pack ${languageId}@${thePreviousVersion} is missing. Downloading previous version...`);
|
||||
return await getSpecificNLS(resourceUrlTemplate, languageId, previousVersion(thePreviousVersion));
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'libdrm2 (>= 2.4.38)',
|
||||
'libexpat1 (>= 2.0.1)',
|
||||
'libgbm1 (>= 8.1~0)',
|
||||
'libgcc1 (>= 1:3.0)',
|
||||
'libgcc-s1 (>= 3.0)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
@@ -85,8 +85,8 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'libdrm2 (>= 2.4.38)',
|
||||
'libexpat1 (>= 2.0.1)',
|
||||
'libgbm1 (>= 8.1~0)',
|
||||
'libgcc1 (>= 1:3.0)',
|
||||
'libgcc1 (>= 1:3.5)',
|
||||
'libgcc-s1 (>= 3.0)',
|
||||
'libgcc-s1 (>= 3.5)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
|
||||
@@ -49,7 +49,7 @@ export const referenceGeneratedDepsByArch = {
|
||||
'libdrm2 (>= 2.4.38)',
|
||||
'libexpat1 (>= 2.0.1)',
|
||||
'libgbm1 (>= 8.1~0)',
|
||||
'libgcc1 (>= 1:3.0)',
|
||||
'libgcc-s1 (>= 3.0)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
@@ -86,8 +86,8 @@ export const referenceGeneratedDepsByArch = {
|
||||
'libdrm2 (>= 2.4.38)',
|
||||
'libexpat1 (>= 2.0.1)',
|
||||
'libgbm1 (>= 8.1~0)',
|
||||
'libgcc1 (>= 1:3.0)',
|
||||
'libgcc1 (>= 1:3.5)',
|
||||
'libgcc-s1 (>= 3.0)',
|
||||
'libgcc-s1 (>= 3.5)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
|
||||
@@ -10,6 +10,7 @@ const fs_1 = require("fs");
|
||||
const os_1 = require("os");
|
||||
const path = require("path");
|
||||
const dep_lists_1 = require("./dep-lists");
|
||||
const manifests = require("../../../cgmanifest.json");
|
||||
// A flag that can easily be toggled.
|
||||
// Make sure to compile the build directory after toggling the value.
|
||||
// If false, we warn about new dependencies if they show up
|
||||
@@ -76,7 +77,10 @@ function calculatePackageDeps(binaryPath, arch, sysroot) {
|
||||
console.error('Tried to stat ' + binaryPath + ' but failed.');
|
||||
}
|
||||
// Get the Chromium dpkg-shlibdeps file.
|
||||
const dpkgShlibdepsUrl = 'https://raw.githubusercontent.com/chromium/chromium/100.0.4896.160/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl';
|
||||
const chromiumManifest = manifests.registrations.filter(registration => {
|
||||
return registration.component.type === 'git' && registration.component.git.name === 'chromium';
|
||||
});
|
||||
const dpkgShlibdepsUrl = `https://raw.githubusercontent.com/chromium/chromium/${chromiumManifest[0].version}/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl`;
|
||||
const dpkgShlibdepsScriptLocation = `${(0, os_1.tmpdir)()}/dpkg-shlibdeps.pl`;
|
||||
const result = (0, child_process_1.spawnSync)('curl', [dpkgShlibdepsUrl, '-o', dpkgShlibdepsScriptLocation]);
|
||||
if (result.status !== 0) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { tmpdir } from 'os';
|
||||
import path = require('path');
|
||||
import { additionalDeps, bundledDeps, referenceGeneratedDepsByArch } from './dep-lists';
|
||||
import { ArchString } from './types';
|
||||
import * as manifests from '../../../cgmanifest.json';
|
||||
|
||||
// A flag that can easily be toggled.
|
||||
// Make sure to compile the build directory after toggling the value.
|
||||
@@ -86,7 +87,10 @@ function calculatePackageDeps(binaryPath: string, arch: ArchString, sysroot: str
|
||||
}
|
||||
|
||||
// Get the Chromium dpkg-shlibdeps file.
|
||||
const dpkgShlibdepsUrl = 'https://raw.githubusercontent.com/chromium/chromium/100.0.4896.160/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl';
|
||||
const chromiumManifest = manifests.registrations.filter(registration => {
|
||||
return registration.component.type === 'git' && registration.component.git!.name === 'chromium';
|
||||
});
|
||||
const dpkgShlibdepsUrl = `https://raw.githubusercontent.com/chromium/chromium/${chromiumManifest[0].version}/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl`;
|
||||
const dpkgShlibdepsScriptLocation = `${tmpdir()}/dpkg-shlibdeps.pl`;
|
||||
const result = spawnSync('curl', [dpkgShlibdepsUrl, '-o', dpkgShlibdepsScriptLocation]);
|
||||
if (result.status !== 0) {
|
||||
|
||||
@@ -11,7 +11,7 @@ const os_1 = require("os");
|
||||
const fs = require("fs");
|
||||
const https = require("https");
|
||||
const path = require("path");
|
||||
const sysroots_1 = require("./sysroots");
|
||||
const util = require("../../lib/util");
|
||||
// Based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/install-sysroot.py.
|
||||
const URL_PREFIX = 'https://msftelectron.blob.core.windows.net';
|
||||
const URL_PATH = 'sysroots/toolchain';
|
||||
@@ -30,7 +30,15 @@ function getSha(filename) {
|
||||
return hash.digest('hex');
|
||||
}
|
||||
async function getSysroot(arch) {
|
||||
const sysrootDict = sysroots_1.sysrootInfo[arch];
|
||||
const sysrootJSONUrl = `https://raw.githubusercontent.com/electron/electron/v${util.getElectronVersion()}/script/sysroots.json`;
|
||||
const sysrootDictLocation = `${(0, os_1.tmpdir)()}/sysroots.json`;
|
||||
const result = (0, child_process_1.spawnSync)('curl', [sysrootJSONUrl, '-o', sysrootDictLocation]);
|
||||
if (result.status !== 0) {
|
||||
throw new Error('Cannot retrieve sysroots.json. Stderr:\n' + result.stderr);
|
||||
}
|
||||
const sysrootInfo = require(sysrootDictLocation);
|
||||
const sysrootArch = arch === 'armhf' ? 'bullseye_arm' : `bullseye_${arch}`;
|
||||
const sysrootDict = sysrootInfo[sysrootArch];
|
||||
const tarballFilename = sysrootDict['Tarball'];
|
||||
const tarballSha = sysrootDict['Sha1Sum'];
|
||||
const sysroot = path.join((0, os_1.tmpdir)(), sysrootDict['SysrootDir']);
|
||||
|
||||
@@ -9,8 +9,8 @@ import { tmpdir } from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as https from 'https';
|
||||
import * as path from 'path';
|
||||
import { sysrootInfo } from './sysroots';
|
||||
import { ArchString } from './types';
|
||||
import * as util from '../../lib/util';
|
||||
|
||||
// Based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/install-sysroot.py.
|
||||
const URL_PREFIX = 'https://msftelectron.blob.core.windows.net';
|
||||
@@ -38,7 +38,15 @@ type SysrootDictEntry = {
|
||||
};
|
||||
|
||||
export async function getSysroot(arch: ArchString): Promise<string> {
|
||||
const sysrootDict: SysrootDictEntry = sysrootInfo[arch];
|
||||
const sysrootJSONUrl = `https://raw.githubusercontent.com/electron/electron/v${util.getElectronVersion()}/script/sysroots.json`;
|
||||
const sysrootDictLocation = `${tmpdir()}/sysroots.json`;
|
||||
const result = spawnSync('curl', [sysrootJSONUrl, '-o', sysrootDictLocation]);
|
||||
if (result.status !== 0) {
|
||||
throw new Error('Cannot retrieve sysroots.json. Stderr:\n' + result.stderr);
|
||||
}
|
||||
const sysrootInfo = require(sysrootDictLocation);
|
||||
const sysrootArch = arch === 'armhf' ? 'bullseye_arm' : `bullseye_${arch}`;
|
||||
const sysrootDict: SysrootDictEntry = sysrootInfo[sysrootArch];
|
||||
const tarballFilename = sysrootDict['Tarball'];
|
||||
const tarballSha = sysrootDict['Sha1Sum'];
|
||||
const sysroot = path.join(tmpdir(), sysrootDict['SysrootDir']);
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sysrootInfo = void 0;
|
||||
// Based on https://github.com/electron/electron/blob/main/script/sysroots.json,
|
||||
// which itself is based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/sysroots.json.
|
||||
exports.sysrootInfo = {
|
||||
'amd64': {
|
||||
'Sha1Sum': '7e008cea9eae822d80d55c67fbb5ef4204678e74',
|
||||
'SysrootDir': 'debian_sid_amd64-sysroot',
|
||||
'Tarball': 'debian_sid_amd64_sysroot.tar.xz'
|
||||
},
|
||||
'armhf': {
|
||||
'Sha1Sum': 'b6f4bb07817bea91b06514a9c1e3832df5a90dbf',
|
||||
'SysrootDir': 'debian_sid_arm-sysroot',
|
||||
'Tarball': 'debian_sid_arm_sysroot.tar.xz'
|
||||
},
|
||||
'arm64': {
|
||||
'Sha1Sum': '5a56c1ef714154ea5003bcafb16f21b0f8dde023',
|
||||
'SysrootDir': 'debian_sid_arm64-sysroot',
|
||||
'Tarball': 'debian_sid_arm64_sysroot.tar.xz'
|
||||
}
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// Based on https://github.com/electron/electron/blob/main/script/sysroots.json,
|
||||
// which itself is based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/sysroots.json.
|
||||
export const sysrootInfo = {
|
||||
'amd64': {
|
||||
'Sha1Sum': '7e008cea9eae822d80d55c67fbb5ef4204678e74',
|
||||
'SysrootDir': 'debian_sid_amd64-sysroot',
|
||||
'Tarball': 'debian_sid_amd64_sysroot.tar.xz'
|
||||
},
|
||||
'armhf': {
|
||||
'Sha1Sum': 'b6f4bb07817bea91b06514a9c1e3832df5a90dbf',
|
||||
'SysrootDir': 'debian_sid_arm-sysroot',
|
||||
'Tarball': 'debian_sid_arm_sysroot.tar.xz'
|
||||
},
|
||||
'arm64': {
|
||||
'Sha1Sum': '5a56c1ef714154ea5003bcafb16f21b0f8dde023',
|
||||
'SysrootDir': 'debian_sid_arm64-sysroot',
|
||||
'Tarball': 'debian_sid_arm64_sysroot.tar.xz'
|
||||
}
|
||||
};
|
||||
+6
-6
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "chromium",
|
||||
"repositoryUrl": "https://chromium.googlesource.com/chromium/src",
|
||||
"commitHash": "59f4a82f7cf9fd0397aa7bf0273bf5b62433c5da"
|
||||
"commitHash": "16e28102fdf876ce6d136674ba66343ede07441f"
|
||||
}
|
||||
},
|
||||
"licenseDetail": [
|
||||
@@ -40,7 +40,7 @@
|
||||
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
],
|
||||
"isOnlyProductionDependency": true,
|
||||
"version": "100.0.4896.160"
|
||||
"version": "102.0.5005.167"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
@@ -48,11 +48,11 @@
|
||||
"git": {
|
||||
"name": "nodejs",
|
||||
"repositoryUrl": "https://github.com/nodejs/node",
|
||||
"commitHash": "acb71eab779fb56bf70e8a9e0cb2e82a089a87de"
|
||||
"commitHash": "442e84a358d75152556b5d087e4dd6a51615330d"
|
||||
}
|
||||
},
|
||||
"isOnlyProductionDependency": true,
|
||||
"version": "16.13.2"
|
||||
"version": "16.14.2"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
@@ -60,12 +60,12 @@
|
||||
"git": {
|
||||
"name": "electron",
|
||||
"repositoryUrl": "https://github.com/electron/electron",
|
||||
"commitHash": "6165f6afc9af6f9ab4e32f4a7a8b0818f11e766a"
|
||||
"commitHash": "a5cafd174d2027529d0b251e5b8e58da2b364e5b"
|
||||
}
|
||||
},
|
||||
"isOnlyProductionDependency": true,
|
||||
"license": "MIT",
|
||||
"version": "18.3.5"
|
||||
"version": "19.0.11"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
|
||||
@@ -177,6 +177,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codespaces": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "Codespaces-specific configuration.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/codespaces' instead"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,29 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensions": {
|
||||
"type": "array",
|
||||
"description": "An array of extensions that should be installed into the container.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$",
|
||||
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
|
||||
},
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/extensions' instead"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "vscode://schemas/settings/machine",
|
||||
"description": "Machine specific settings that should be copied into the container. These are only copied when connecting to the container for the first time, rebuilding the container then triggers it again.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/settings' instead"
|
||||
},
|
||||
"devPort": {
|
||||
"type": "integer",
|
||||
"description": "The port VS Code can use to connect to its backend.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/devPort' instead"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"emmet.showAbbreviationSuggestions": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"scope": "language-overridable",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%emmetShowAbbreviationSuggestions%"
|
||||
},
|
||||
"emmet.includeLanguages": {
|
||||
|
||||
@@ -264,47 +264,47 @@ export async function wrapWithAbbreviation(args: any): Promise<boolean> {
|
||||
}
|
||||
|
||||
export function expandEmmetAbbreviation(args: any): Thenable<boolean | undefined> {
|
||||
if (!validate() || !vscode.window.activeTextEditor) {
|
||||
return fallbackTab();
|
||||
if (!validate()) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor!;
|
||||
|
||||
args = args || {};
|
||||
if (!args['language']) {
|
||||
args['language'] = editor.document.languageId;
|
||||
} else {
|
||||
const excludedLanguages = vscode.workspace.getConfiguration('emmet')['excludeLanguages'] ?? [];
|
||||
if (excludedLanguages.includes(args['language'])) {
|
||||
return fallbackTab(args['language']);
|
||||
}
|
||||
}
|
||||
const languageId: string = args['language'];
|
||||
|
||||
/**
|
||||
* Short circuit the parsing. If previous character is space, do not expand.
|
||||
*/
|
||||
if (vscode.window.activeTextEditor.selections.length === 1 &&
|
||||
vscode.window.activeTextEditor.selection.isEmpty
|
||||
if (editor.selections.length === 1 && editor.selection.isEmpty
|
||||
) {
|
||||
const anchor = vscode.window.activeTextEditor.selection.anchor;
|
||||
const anchor = editor.selection.anchor;
|
||||
if (anchor.character === 0) {
|
||||
return fallbackTab();
|
||||
return fallbackTab(languageId);
|
||||
}
|
||||
|
||||
const prevPositionAnchor = anchor.translate(0, -1);
|
||||
const prevText = vscode.window.activeTextEditor.document.getText(new vscode.Range(prevPositionAnchor, anchor));
|
||||
const prevText = editor.document.getText(new vscode.Range(prevPositionAnchor, anchor));
|
||||
if (prevText === ' ' || prevText === '\t') {
|
||||
return fallbackTab();
|
||||
return fallbackTab(languageId);
|
||||
}
|
||||
}
|
||||
|
||||
args = args || {};
|
||||
if (!args['language']) {
|
||||
args['language'] = vscode.window.activeTextEditor.document.languageId;
|
||||
} else {
|
||||
const excludedLanguages = vscode.workspace.getConfiguration('emmet')['excludeLanguages'] ? vscode.workspace.getConfiguration('emmet')['excludeLanguages'] : [];
|
||||
if (excludedLanguages.indexOf(vscode.window.activeTextEditor.document.languageId) > -1) {
|
||||
return fallbackTab();
|
||||
}
|
||||
}
|
||||
const syntax = getSyntaxFromArgs(args);
|
||||
if (!syntax) {
|
||||
return fallbackTab();
|
||||
return fallbackTab(languageId);
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
|
||||
// When tabbed on a non empty selection, do not treat it as an emmet abbreviation, and fallback to tab instead
|
||||
if (vscode.workspace.getConfiguration('emmet')['triggerExpansionOnTab'] === true && editor.selections.find(x => !x.isEmpty)) {
|
||||
return fallbackTab();
|
||||
if (vscode.workspace.getConfiguration('emmet', { languageId })['triggerExpansionOnTab'] === true && editor.selections.find(x => !x.isEmpty)) {
|
||||
return fallbackTab(languageId);
|
||||
}
|
||||
|
||||
const abbreviationList: ExpandAbbreviationInput[] = [];
|
||||
@@ -325,7 +325,7 @@ export function expandEmmetAbbreviation(args: any): Thenable<boolean | undefined
|
||||
}
|
||||
|
||||
const currentLine = editor.document.lineAt(position.line).text;
|
||||
const textTillPosition = currentLine.substr(0, position.character);
|
||||
const textTillPosition = currentLine.substring(0, position.character);
|
||||
|
||||
// Expand cases like <div to <div></div> explicitly
|
||||
// else we will end up with <<div></div>
|
||||
@@ -415,12 +415,12 @@ export function expandEmmetAbbreviation(args: any): Thenable<boolean | undefined
|
||||
});
|
||||
|
||||
return expandAbbreviationInRange(editor, abbreviationList, allAbbreviationsSame).then(success => {
|
||||
return success ? Promise.resolve(undefined) : fallbackTab();
|
||||
return success ? Promise.resolve(undefined) : fallbackTab(languageId);
|
||||
});
|
||||
}
|
||||
|
||||
function fallbackTab(): Thenable<boolean | undefined> {
|
||||
if (vscode.workspace.getConfiguration('emmet')['triggerExpansionOnTab'] === true) {
|
||||
function fallbackTab(languageId: string): Thenable<boolean | undefined> {
|
||||
if (vscode.workspace.getConfiguration('emmet', { languageId })['triggerExpansionOnTab'] === true) {
|
||||
return vscode.commands.executeCommand('tab');
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
@@ -470,13 +470,13 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen
|
||||
&& propertyNode.separator
|
||||
&& offset >= propertyNode.separatorToken.end
|
||||
&& offset <= propertyNode.terminatorToken.start
|
||||
&& abbreviation.indexOf(':') === -1) {
|
||||
&& !abbreviation.includes(':')) {
|
||||
return hexColorRegex.test(abbreviation) || abbreviation === '!';
|
||||
}
|
||||
if (!propertyNode.terminatorToken
|
||||
&& propertyNode.separator
|
||||
&& offset >= propertyNode.separatorToken.end
|
||||
&& abbreviation.indexOf(':') === -1) {
|
||||
&& !abbreviation.includes(':')) {
|
||||
return hexColorRegex.test(abbreviation) || abbreviation === '!';
|
||||
}
|
||||
if (hexColorRegex.test(abbreviation) || abbreviation === '!') {
|
||||
@@ -529,7 +529,7 @@ export function isValidLocationForEmmetAbbreviation(document: vscode.TextDocumen
|
||||
const typeAttribute = (currentHtmlNode.attributes || []).filter(x => x.name.toString() === 'type')[0];
|
||||
const typeValue = typeAttribute ? typeAttribute.value.toString() : '';
|
||||
|
||||
if (allowedMimeTypesInScriptTag.indexOf(typeValue) > -1) {
|
||||
if (allowedMimeTypesInScriptTag.includes(typeValue)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
|
||||
|
||||
if (expandedText.startsWith('<')) {
|
||||
this.lastCompletionType = 'html';
|
||||
} else if (expandedText.indexOf(':') > 0 && expandedText.endsWith(';')) {
|
||||
} else if (expandedText.includes(':') && expandedText.endsWith(';')) {
|
||||
this.lastCompletionType = 'css';
|
||||
} else {
|
||||
this.lastCompletionType = undefined;
|
||||
@@ -43,7 +43,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
|
||||
private provideCompletionItemsInternal(document: vscode.TextDocument, position: vscode.Position, context: vscode.CompletionContext): Thenable<vscode.CompletionList | undefined> | undefined {
|
||||
const emmetConfig = vscode.workspace.getConfiguration('emmet');
|
||||
const excludedLanguages = emmetConfig['excludeLanguages'] ? emmetConfig['excludeLanguages'] : [];
|
||||
if (excludedLanguages.indexOf(document.languageId) > -1) {
|
||||
if (excludedLanguages.includes(document.languageId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ function getNextAttribute(document: vscode.TextDocument, selectionStart: number,
|
||||
}
|
||||
|
||||
// Fetch the next word in the attr value
|
||||
if (attr.value.toString().indexOf(' ') === -1) {
|
||||
if (!attr.value.toString().includes(' ')) {
|
||||
// attr value does not have space, so no next word to find
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ export class GitHubServer implements IGitHubServer {
|
||||
try {
|
||||
return await Promise.race([
|
||||
codeExchangePromise.promise,
|
||||
new Promise<string>((_, reject) => setTimeout(() => reject('Cancelled'), 60000)),
|
||||
new Promise<string>((_, reject) => setTimeout(() => reject('Timed out'), 300_000)), // 5min timeout
|
||||
promiseFromEvent<any, any>(token.onCancellationRequested, (_, __, reject) => { reject('User Cancelled'); }).promise
|
||||
]);
|
||||
} finally {
|
||||
@@ -276,7 +276,7 @@ export class GitHubServer implements IGitHubServer {
|
||||
vscode.env.openExternal(vscode.Uri.parse(`http://127.0.0.1:${port}/signin?nonce=${encodeURIComponent(server.nonce)}`));
|
||||
const { code } = await Promise.race([
|
||||
server.waitForOAuthResponse(),
|
||||
new Promise<any>((_, reject) => setTimeout(() => reject('Cancelled'), 60000)),
|
||||
new Promise<any>((_, reject) => setTimeout(() => reject('Timed out'), 300_000)), // 5min timeout
|
||||
promiseFromEvent<any, any>(token.onCancellationRequested, (_, __, reject) => { reject('User Cancelled'); }).promise
|
||||
]);
|
||||
codeToExchange = code;
|
||||
|
||||
@@ -9,9 +9,13 @@ import { publishRepository } from './publish';
|
||||
import { DisposableStore } from './util';
|
||||
import { getPermalink } from './links';
|
||||
|
||||
function getVscodeDevHost(): string {
|
||||
return `https://${vscode.env.appName.toLowerCase().includes('insiders') ? 'insiders.' : ''}vscode.dev/github`;
|
||||
}
|
||||
|
||||
async function copyVscodeDevLink(gitAPI: GitAPI, useSelection: boolean) {
|
||||
try {
|
||||
const permalink = getPermalink(gitAPI, useSelection, 'https://vscode.dev/github');
|
||||
const permalink = getPermalink(gitAPI, useSelection, getVscodeDevHost());
|
||||
if (permalink) {
|
||||
return vscode.env.clipboard.writeText(permalink);
|
||||
}
|
||||
@@ -22,7 +26,7 @@ async function copyVscodeDevLink(gitAPI: GitAPI, useSelection: boolean) {
|
||||
|
||||
async function openVscodeDevLink(gitAPI: GitAPI): Promise<vscode.Uri | undefined> {
|
||||
try {
|
||||
const permalink = getPermalink(gitAPI, true, 'https://vscode.dev/github');
|
||||
const permalink = getPermalink(gitAPI, true, getVscodeDevHost());
|
||||
return permalink ? vscode.Uri.parse(permalink) : undefined;
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err.message);
|
||||
|
||||
@@ -125,11 +125,11 @@ export function getPermalink(gitAPI: GitAPI, useSelection: boolean, hostPrefix?:
|
||||
return;
|
||||
}
|
||||
|
||||
const commitHash = gitRepo.state.HEAD?.commit;
|
||||
const commitHash = (gitRepo.state.HEAD?.ahead === 0) ? `/blob/${gitRepo.state.HEAD?.commit}` : '';
|
||||
const fileSegments = fileAndPosition.type === LinkType.File
|
||||
? (useSelection ? `${uri.path.substring(gitRepo.rootUri.path.length)}${rangeString(fileAndPosition.range)}` : '')
|
||||
: (useSelection ? `${uri.path.substring(gitRepo.rootUri.path.length)}${notebookCellRangeString(fileAndPosition.cellIndex, fileAndPosition.range)}` : '');
|
||||
|
||||
return `${hostPrefix}/${repo.owner}/${repo.repo}/blob/${commitHash
|
||||
return `${hostPrefix}/${repo.owner}/${repo.repo}${commitHash
|
||||
}${fileSegments}`;
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ extension.webpack.config.js
|
||||
extension-browser.webpack.config.js
|
||||
yarn.lock
|
||||
.gitignore
|
||||
|
||||
esbuild.js
|
||||
|
||||
@@ -22,11 +22,19 @@ export async function activate(ctx: RendererContext<void>) {
|
||||
md.renderer.rules.image = (tokens: MarkdownItToken[], idx: number, options, env, self) => {
|
||||
const token = tokens[idx];
|
||||
const src = token.attrGet('src');
|
||||
const attachments: Record<string, Record<string, string>> = env.outputItem.metadata?.custom?.attachments;
|
||||
const attachments: Record<string, Record<string, string>> = env.outputItem.metadata().custom?.attachments;
|
||||
if (attachments && src) {
|
||||
const [attachmentKey, attachmentVal] = Object.entries(attachments[src.replace('attachment:', '')])[0];
|
||||
const b64Markdown = 'data:' + attachmentKey + ';base64,' + attachmentVal;
|
||||
token.attrSet('src', b64Markdown);
|
||||
const imageAttachment = attachments[src.replace('attachment:', '')];
|
||||
if (imageAttachment) {
|
||||
// objEntries will always be length 1, with objEntries[0] holding [0]=mime,[1]=b64
|
||||
// if length = 0, something is wrong with the attachment, mime/b64 weren't copied over
|
||||
const objEntries = Object.entries(imageAttachment);
|
||||
if (objEntries.length) {
|
||||
const [attachmentKey, attachmentVal] = objEntries[0];
|
||||
const b64Markdown = 'data:' + attachmentKey + ';base64,' + attachmentVal;
|
||||
token.attrSet('src', b64Markdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (original) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { v4 as uuid } from 'uuid';
|
||||
import { getCellMetadata } from './serializers';
|
||||
import { CellMetadata } from './common';
|
||||
import { getNotebookMetadata } from './notebookSerializer';
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
|
||||
/**
|
||||
* Ensure all new cells in notebooks with nbformat >= 4.5 have an id.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
|
||||
/**
|
||||
* Metadata we store in VS Code cell output items.
|
||||
@@ -44,7 +44,7 @@ export interface CellOutputMetadata {
|
||||
|
||||
/**
|
||||
* Metadata we store in VS Code cells.
|
||||
* This contains the original metadata from the Jupyuter cells.
|
||||
* This contains the original metadata from the Jupyter cells.
|
||||
*/
|
||||
export interface CellMetadata {
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
import { extensions, NotebookCellData, NotebookCellExecutionSummary, NotebookCellKind, NotebookCellOutput, NotebookCellOutputItem, NotebookData } from 'vscode';
|
||||
import { CellMetadata, CellOutputMetadata } from './common';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
import * as detectIndent from 'detect-indent';
|
||||
import * as vscode from 'vscode';
|
||||
import { defaultNotebookFormat } from './constants';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
import { NotebookCell, NotebookCellData, NotebookCellKind, NotebookCellOutput } from 'vscode';
|
||||
import { CellMetadata, CellOutputMetadata } from './common';
|
||||
import { textMimeTypes } from './deserializers';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nbformat from '@jupyterlab/nbformat';
|
||||
import type * as nbformat from '@jupyterlab/nbformat';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { jupyterCellOutputToCellOutput, jupyterNotebookModelToNotebookData } from '../deserializers';
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"git": {
|
||||
"name": "microsoft/vscode-markdown-tm-grammar",
|
||||
"repositoryUrl": "https://github.com/microsoft/vscode-markdown-tm-grammar",
|
||||
"commitHash": "69d3321b4923ca2d5e8e900018887cc38b5fe04a"
|
||||
"commitHash": "97f2f8d38f10d3febd77d85b745945dc60fe334e"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/69d3321b4923ca2d5e8e900018887cc38b5fe04a",
|
||||
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/97f2f8d38f10d3febd77d85b745945dc60fe334e",
|
||||
"name": "Markdown",
|
||||
"scopeName": "text.html.markdown",
|
||||
"patterns": [
|
||||
@@ -2766,7 +2766,24 @@
|
||||
"name": "punctuation.definition.link.title.begin.markdown"
|
||||
},
|
||||
"2": {
|
||||
"name": "string.other.link.title.markdown"
|
||||
"name": "string.other.link.title.markdown",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#raw"
|
||||
},
|
||||
{
|
||||
"include": "#bold"
|
||||
},
|
||||
{
|
||||
"include": "#italic"
|
||||
},
|
||||
{
|
||||
"include": "#strikethrough"
|
||||
},
|
||||
{
|
||||
"include": "#image-inline"
|
||||
}
|
||||
]
|
||||
},
|
||||
"4": {
|
||||
"name": "punctuation.definition.link.title.end.markdown"
|
||||
@@ -2826,7 +2843,24 @@
|
||||
"name": "punctuation.definition.link.title.begin.markdown"
|
||||
},
|
||||
"2": {
|
||||
"name": "string.other.link.title.markdown"
|
||||
"name": "string.other.link.title.markdown",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#raw"
|
||||
},
|
||||
{
|
||||
"include": "#bold"
|
||||
},
|
||||
{
|
||||
"include": "#italic"
|
||||
},
|
||||
{
|
||||
"include": "#strikethrough"
|
||||
},
|
||||
{
|
||||
"include": "#image-inline"
|
||||
}
|
||||
]
|
||||
},
|
||||
"4": {
|
||||
"name": "punctuation.definition.link.title.end.markdown"
|
||||
@@ -2957,7 +2991,7 @@
|
||||
"name": "punctuation.definition.strikethrough.markdown"
|
||||
}
|
||||
},
|
||||
"match": "(~{2,})((?:[^~]|(?!(?<!~)\\1(?!~))~)*+)(\\1)",
|
||||
"match": "(?<!\\\\)(~{2,})((?:[^~]|(?!(?<![~\\\\])\\1(?!~))~)*+)(\\1)",
|
||||
"name": "markup.strikethrough.markdown"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ cgmanifest.json
|
||||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
esbuild.js
|
||||
esbuild-notebook.js
|
||||
esbuild-preview.js
|
||||
.gitignore
|
||||
server/src/**
|
||||
server/extension.webpack.config.js
|
||||
|
||||
@@ -187,22 +187,22 @@
|
||||
},
|
||||
{
|
||||
"command": "markdown.showSource",
|
||||
"when": "markdownPreviewFocus",
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "markdown.preview.refresh",
|
||||
"when": "markdownPreviewFocus",
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'",
|
||||
"group": "1_markdown"
|
||||
},
|
||||
{
|
||||
"command": "markdown.preview.toggleLock",
|
||||
"when": "markdownPreviewFocus",
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'",
|
||||
"group": "1_markdown"
|
||||
},
|
||||
{
|
||||
"command": "markdown.showPreviewSecuritySelector",
|
||||
"when": "markdownPreviewFocus",
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'",
|
||||
"group": "1_markdown"
|
||||
}
|
||||
],
|
||||
@@ -247,7 +247,7 @@
|
||||
},
|
||||
{
|
||||
"command": "markdown.showSource",
|
||||
"when": "markdownPreviewFocus",
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
@@ -256,11 +256,11 @@
|
||||
},
|
||||
{
|
||||
"command": "markdown.showPreviewSecuritySelector",
|
||||
"when": "markdownPreviewFocus"
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'"
|
||||
},
|
||||
{
|
||||
"command": "markdown.preview.toggleLock",
|
||||
"when": "markdownPreviewFocus"
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'"
|
||||
},
|
||||
{
|
||||
"command": "markdown.preview.refresh",
|
||||
@@ -268,7 +268,7 @@
|
||||
},
|
||||
{
|
||||
"command": "markdown.preview.refresh",
|
||||
"when": "markdownPreviewFocus"
|
||||
"when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'"
|
||||
},
|
||||
{
|
||||
"command": "markdown.findAllFileReferences",
|
||||
@@ -515,7 +515,11 @@
|
||||
"configurationDefaults": {
|
||||
"[markdown]": {
|
||||
"editor.wordWrap": "on",
|
||||
"editor.quickSuggestions": false
|
||||
"editor.quickSuggestions": {
|
||||
"comments": "off",
|
||||
"strings": "off",
|
||||
"other": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonValidation": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vscode-markdown-languageserver",
|
||||
"description": "Markdown language server",
|
||||
"version": "0.0.0-alpha-1",
|
||||
"version": "0.0.0-alpha-2",
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -10,10 +10,10 @@
|
||||
"main": "./out/node/main",
|
||||
"browser": "./dist/browser/main",
|
||||
"dependencies": {
|
||||
"vscode-languageserver": "^8.0.2-next.5`",
|
||||
"vscode-languageserver": "^8.0.2",
|
||||
"vscode-languageserver-textdocument": "^1.0.5",
|
||||
"vscode-languageserver-types": "^3.17.1",
|
||||
"vscode-markdown-languageservice": "^0.0.0-alpha.12",
|
||||
"vscode-markdown-languageservice": "^0.0.0-alpha.13",
|
||||
"vscode-uri": "^3.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -48,13 +48,13 @@ export function registerValidateSupport(
|
||||
workspace: VsCodeClientWorkspace,
|
||||
ls: md.IMdLanguageService,
|
||||
config: ConfigurationManager,
|
||||
logger: md.ILogger,
|
||||
): Disposable {
|
||||
let diagnosticOptions: md.DiagnosticOptions = defaultDiagnosticOptions;
|
||||
function updateDiagnosticsSetting(): void {
|
||||
diagnosticOptions = getDiagnosticsOptions(config);
|
||||
}
|
||||
|
||||
|
||||
const subs: Disposable[] = [];
|
||||
const manager = ls.createPullDiagnosticsManager();
|
||||
subs.push(manager);
|
||||
@@ -64,14 +64,23 @@ export function registerValidateSupport(
|
||||
connection.languages.diagnostics.refresh();
|
||||
}));
|
||||
|
||||
const emptyDiagnosticsResponse = Object.freeze({ kind: 'full', items: [] });
|
||||
|
||||
connection.languages.diagnostics.on(async (params, token): Promise<FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport> => {
|
||||
logger.log(md.LogLevel.Trace, 'Server: connection.languages.diagnostics.on', params.textDocument.uri);
|
||||
|
||||
if (!config.getSettings()?.markdown.experimental.validate.enabled) {
|
||||
return { kind: 'full', items: [] };
|
||||
return emptyDiagnosticsResponse;
|
||||
}
|
||||
|
||||
const document = await workspace.openMarkdownDocument(URI.parse(params.textDocument.uri));
|
||||
const uri = URI.parse(params.textDocument.uri);
|
||||
if (!workspace.hasMarkdownDocument(uri)) {
|
||||
return emptyDiagnosticsResponse;
|
||||
}
|
||||
|
||||
const document = await workspace.openMarkdownDocument(uri);
|
||||
if (!document) {
|
||||
return { kind: 'full', items: [] };
|
||||
return emptyDiagnosticsResponse;
|
||||
}
|
||||
|
||||
const diagnostics = await manager.computeDiagnostics(document, diagnosticOptions, token);
|
||||
|
||||
@@ -48,7 +48,7 @@ export async function startServer(connection: Connection) {
|
||||
});
|
||||
|
||||
registerCompletionsSupport(connection, documents, provider, configurationManager);
|
||||
registerValidateSupport(connection, workspace, provider, configurationManager);
|
||||
registerValidateSupport(connection, workspace, provider, configurationManager, logger);
|
||||
|
||||
workspace.workspaceFolders = (params.workspaceFolders ?? []).map(x => URI.parse(x.uri));
|
||||
return {
|
||||
|
||||
@@ -63,7 +63,12 @@ export class VsCodeClientWorkspace implements md.IWorkspaceWithWatching {
|
||||
});
|
||||
|
||||
documents.onDidClose(e => {
|
||||
this._documentCache.delete(URI.parse(e.document.uri));
|
||||
const uri = URI.parse(e.document.uri);
|
||||
this._documentCache.delete(uri);
|
||||
|
||||
if (this.isRelevantMarkdownDocument(e.document)) {
|
||||
this._onDidDeleteMarkdownDocument.fire(uri);
|
||||
}
|
||||
});
|
||||
|
||||
connection.onDidChangeWatchedFiles(async ({ changes }) => {
|
||||
|
||||
@@ -3,54 +3,49 @@
|
||||
|
||||
|
||||
"@types/node@16.x":
|
||||
version "16.11.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.43.tgz#555e5a743f76b6b897d47f945305b618525ddbe6"
|
||||
integrity sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ==
|
||||
version "16.11.47"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.47.tgz#efa9e3e0f72e7aa6a138055dace7437a83d9f91c"
|
||||
integrity sha512-fpP+jk2zJ4VW66+wAMFoBJlx1bxmBKx4DUFf68UHgdGCOuyUTDlLWqsaNPJh7xhNDykyJ9eIzAygilP/4WoN8g==
|
||||
|
||||
picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
vscode-jsonrpc@8.0.2-next.1:
|
||||
version "8.0.2-next.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2-next.1.tgz#6bdc39fd194782032e34047eeefce562941259c6"
|
||||
integrity sha512-sbbvGSWja7NVBLHPGawtgezc8DHYJaP4qfr/AaJiyDapWcSFtHyPtm18+LnYMLTmB7bhOUW/lf5PeeuLpP6bKA==
|
||||
vscode-jsonrpc@8.0.2:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz#f239ed2cd6004021b6550af9fd9d3e47eee3cac9"
|
||||
integrity sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==
|
||||
|
||||
vscode-languageserver-protocol@3.17.2-next.6:
|
||||
version "3.17.2-next.6"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2-next.6.tgz#8f1dc0fcb29366b85f623a3f9af726de433b5fcc"
|
||||
integrity sha512-WtsebNOOkWyNn4oFYoAMPC8Q/ZDoJ/K7Ja53OzTixiitvrl/RpXZETrtzH79R8P5kqCyx6VFBPb6KQILJfkDkA==
|
||||
vscode-languageserver-protocol@3.17.2:
|
||||
version "3.17.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz#beaa46aea06ed061576586c5e11368a9afc1d378"
|
||||
integrity sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==
|
||||
dependencies:
|
||||
vscode-jsonrpc "8.0.2-next.1"
|
||||
vscode-languageserver-types "3.17.2-next.2"
|
||||
vscode-jsonrpc "8.0.2"
|
||||
vscode-languageserver-types "3.17.2"
|
||||
|
||||
vscode-languageserver-textdocument@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.5.tgz#838769940ece626176ec5d5a2aa2d0aa69f5095c"
|
||||
integrity sha512-1ah7zyQjKBudnMiHbZmxz5bYNM9KKZYz+5VQLj+yr8l+9w3g+WAhCkUkWbhMEdC5u0ub4Ndiye/fDyS8ghIKQg==
|
||||
|
||||
vscode-languageserver-types@3.17.2-next.2:
|
||||
version "3.17.2-next.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2-next.2.tgz#af5d6978eee7682aab87c1419323f5b141ac6596"
|
||||
integrity sha512-TiAkLABgqkVWdAlC3XlOfdhdjIAdVU4YntPUm9kKGbXr+MGwpVnKz2KZMNBcvG0CFx8Hi8qliL0iq+ndPB720w==
|
||||
vscode-languageserver-types@3.17.2, vscode-languageserver-types@^3.17.1:
|
||||
version "3.17.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz#b2c2e7de405ad3d73a883e91989b850170ffc4f2"
|
||||
integrity sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==
|
||||
|
||||
vscode-languageserver-types@^3.17.1:
|
||||
version "3.17.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz#c2d87fa7784f8cac389deb3ff1e2d9a7bef07e16"
|
||||
integrity sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==
|
||||
|
||||
vscode-languageserver@^8.0.2-next.5`:
|
||||
version "8.0.2-next.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-8.0.2-next.5.tgz#39a2dd4c504fb88042375e7ac706a714bdaab4e5"
|
||||
integrity sha512-2ZDb7O/4atS9mJKufPPz637z+51kCyZfgnobFW5eSrUdS3c0UB/nMS4Ng1EavYTX84GVaVMKCrmP0f2ceLmR0A==
|
||||
vscode-languageserver@^8.0.2:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz#cfe2f0996d9dfd40d3854e786b2821604dfec06d"
|
||||
integrity sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==
|
||||
dependencies:
|
||||
vscode-languageserver-protocol "3.17.2-next.6"
|
||||
vscode-languageserver-protocol "3.17.2"
|
||||
|
||||
vscode-markdown-languageservice@^0.0.0-alpha.12:
|
||||
version "0.0.0-alpha.12"
|
||||
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.0-alpha.12.tgz#5a3c7559969c3cb455d508d48129c8e221589630"
|
||||
integrity sha512-9dJ/GL6A9UUOcB1TpvgsbcwqsYjnxHx4jxDaqeZZEMWFSUySfp0PAn1ge2S2Qj00zypvsu0eCTGUNd56G1/BNQ==
|
||||
vscode-markdown-languageservice@^0.0.0-alpha.13:
|
||||
version "0.0.0-alpha.13"
|
||||
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.0.0-alpha.13.tgz#28cd8dd8eca451aaa3db1c92ec97ace53623dd5d"
|
||||
integrity sha512-jgRVBQmdO0aC5Svap1RcAd3x2XOSNWla01GF/rzaVx9M5pEcel4SPz+2H9PYXul6jRKe1oKJF9OOciaiE7pSXQ==
|
||||
dependencies:
|
||||
picomatch "^2.3.1"
|
||||
vscode-languageserver-textdocument "^1.0.5"
|
||||
|
||||
@@ -11,7 +11,6 @@ import { MarkdownContributionProvider } from './markdownExtensions';
|
||||
import { Slugifier } from './slugify';
|
||||
import { ITextDocument } from './types/textDocument';
|
||||
import { Disposable } from './util/dispose';
|
||||
import { stringHash } from './util/hash';
|
||||
import { WebviewResourceProvider } from './util/resources';
|
||||
import { isOfScheme, Schemes } from './util/schemes';
|
||||
import { MdDocumentInfoCache } from './util/workspaceCache';
|
||||
@@ -86,11 +85,11 @@ class TokenCache {
|
||||
|
||||
export interface RenderOutput {
|
||||
html: string;
|
||||
containingImages: { src: string }[];
|
||||
containingImages: Set<string>;
|
||||
}
|
||||
|
||||
interface RenderEnv {
|
||||
containingImages: { src: string }[];
|
||||
containingImages: Set<string>;
|
||||
currentDocument: vscode.Uri | undefined;
|
||||
resourceProvider: WebviewResourceProvider | undefined;
|
||||
}
|
||||
@@ -209,7 +208,7 @@ export class MarkdownItEngine implements IMdParser {
|
||||
: this.tokenizeDocument(input, config, engine);
|
||||
|
||||
const env: RenderEnv = {
|
||||
containingImages: [],
|
||||
containingImages: new Set<string>(),
|
||||
currentDocument: typeof input === 'string' ? undefined : input.uri,
|
||||
resourceProvider,
|
||||
};
|
||||
@@ -248,13 +247,9 @@ export class MarkdownItEngine implements IMdParser {
|
||||
const original = md.renderer.rules.image;
|
||||
md.renderer.rules.image = (tokens: Token[], idx: number, options, env: RenderEnv, self) => {
|
||||
const token = tokens[idx];
|
||||
token.attrJoin('class', 'loading');
|
||||
|
||||
const src = token.attrGet('src');
|
||||
if (src) {
|
||||
env.containingImages?.push({ src });
|
||||
const imgHash = stringHash(src);
|
||||
token.attrSet('id', `image-hash-${imgHash}`);
|
||||
env.containingImages?.add(src);
|
||||
|
||||
if (!token.attrGet('data-src')) {
|
||||
token.attrSet('src', this.toResourceUri(src, env.currentDocument, env.resourceProvider));
|
||||
|
||||
@@ -38,7 +38,7 @@ const previewStrings = {
|
||||
|
||||
export interface MarkdownContentProviderOutput {
|
||||
html: string;
|
||||
containingImages: { src: string }[];
|
||||
containingImages: Set<string>;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ export class MdDocumentRenderer {
|
||||
|
||||
const body = await this.renderBody(markdownDocument, resourceProvider);
|
||||
if (token.isCancellationRequested) {
|
||||
return { html: '', containingImages: [] };
|
||||
return { html: '', containingImages: new Set() };
|
||||
}
|
||||
|
||||
const html = `<!DOCTYPE html>
|
||||
|
||||
@@ -396,9 +396,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private updateImageWatchers(containingImages: { src: string }[]) {
|
||||
const srcs = new Set(containingImages.map(img => img.src));
|
||||
|
||||
private updateImageWatchers(srcs: Set<string>) {
|
||||
// Delete stale file watchers.
|
||||
for (const [src, watcher] of this._fileWatchersBySrc) {
|
||||
if (!srcs.has(src)) {
|
||||
|
||||
@@ -58,8 +58,6 @@ class PreviewStore<T extends IManagedMarkdownPreview> extends Disposable {
|
||||
|
||||
export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer, vscode.CustomTextEditorProvider {
|
||||
|
||||
private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus';
|
||||
|
||||
private readonly _topmostLineMonitor = new TopmostLineMonitor();
|
||||
private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager();
|
||||
|
||||
@@ -216,7 +214,6 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
|
||||
this._contributions,
|
||||
this._tocProvider);
|
||||
|
||||
this.setPreviewActiveContext(true);
|
||||
this._activePreview = preview;
|
||||
return this.registerDynamicPreview(preview);
|
||||
}
|
||||
@@ -250,19 +247,14 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
|
||||
|
||||
private trackActive(preview: IManagedMarkdownPreview): void {
|
||||
preview.onDidChangeViewState(({ webviewPanel }) => {
|
||||
this.setPreviewActiveContext(webviewPanel.active);
|
||||
this._activePreview = webviewPanel.active ? preview : undefined;
|
||||
});
|
||||
|
||||
preview.onDispose(() => {
|
||||
if (this._activePreview === preview) {
|
||||
this.setPreviewActiveContext(false);
|
||||
this._activePreview = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setPreviewActiveContext(value: boolean) {
|
||||
vscode.commands.executeCommand('setContext', MarkdownPreviewManager.markdownPreviewActiveContextKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,22 +30,23 @@ suite('markdown.engine', () => {
|
||||
});
|
||||
});
|
||||
|
||||
suite('image-caching', () => {
|
||||
suite.only('image-caching', () => {
|
||||
const input = ' [](no-img.png)   ';
|
||||
|
||||
test('Extracts all images', async () => {
|
||||
const engine = createNewMarkdownEngine();
|
||||
assert.deepStrictEqual((await engine.render(input)), {
|
||||
html: '<p data-line="0" class="code-line" dir="auto">'
|
||||
+ '<img src="img.png" alt="" class="loading" id="image-hash--754511435" data-src="img.png"> '
|
||||
+ '<a href="no-img.png" data-href="no-img.png"></a> '
|
||||
+ '<img src="http://example.org/img.png" alt="" class="loading" id="image-hash--1903814170" data-src="http://example.org/img.png"> '
|
||||
+ '<img src="img.png" alt="" class="loading" id="image-hash--754511435" data-src="img.png"> '
|
||||
+ '<img src="./img2.png" alt="" class="loading" id="image-hash-265238964" data-src="./img2.png">'
|
||||
+ '</p>\n'
|
||||
,
|
||||
containingImages: [{ src: 'img.png' }, { src: 'http://example.org/img.png' }, { src: 'img.png' }, { src: './img2.png' }],
|
||||
});
|
||||
const result = await engine.render(input);
|
||||
assert.deepStrictEqual(result.html,
|
||||
'<p data-line="0" class="code-line" dir="auto">'
|
||||
+ '<img src="img.png" alt="" data-src="img.png"> '
|
||||
+ '<a href="no-img.png" data-href="no-img.png"></a> '
|
||||
+ '<img src="http://example.org/img.png" alt="" data-src="http://example.org/img.png"> '
|
||||
+ '<img src="img.png" alt="" data-src="img.png"> '
|
||||
+ '<img src="./img2.png" alt="" data-src="./img2.png">'
|
||||
+ '</p>\n'
|
||||
);
|
||||
|
||||
assert.deepStrictEqual([...result.containingImages], ['img.png', 'http://example.org/img.png', './img2.png']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
function numberHash(val: number, initialHashVal: number): number {
|
||||
return (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32
|
||||
}
|
||||
|
||||
export function stringHash(s: string) {
|
||||
let hashVal = numberHash(149417, 0);
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
hashVal = numberHash(s.charCodeAt(i), hashVal);
|
||||
}
|
||||
return hashVal;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import * as nls from 'vscode-nls';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import Logger from './logger';
|
||||
import { toBase64UrlEncoding } from './utils';
|
||||
import { isSupportedEnvironment, toBase64UrlEncoding } from './utils';
|
||||
import { sha256 } from './env/node/sha256';
|
||||
import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage';
|
||||
import { LoopbackAuthServer } from './authServer';
|
||||
@@ -319,13 +319,7 @@ export class AzureActiveDirectoryService {
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
const token = await this.exchangeCodeForToken(codeToExchange, codeVerifier, scopeData);
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
|
||||
const session = await this.convertToSession(token);
|
||||
const session = await this.exchangeCodeForSession(codeToExchange, codeVerifier, scopeData);
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -355,9 +349,11 @@ export class AzureActiveDirectoryService {
|
||||
const uri = vscode.Uri.parse(`${signInUrl}?${oauthStartQuery.toString()}`);
|
||||
vscode.env.openExternal(uri);
|
||||
|
||||
let inputBox: vscode.InputBox | undefined;
|
||||
const timeoutPromise = new Promise((_: (value: vscode.AuthenticationSession) => void, reject) => {
|
||||
const wait = setTimeout(() => {
|
||||
clearTimeout(wait);
|
||||
inputBox?.dispose();
|
||||
reject('Login timed out.');
|
||||
}, 1000 * 60 * 5);
|
||||
});
|
||||
@@ -369,7 +365,12 @@ export class AzureActiveDirectoryService {
|
||||
// before completing it.
|
||||
let existingPromise = this._codeExchangePromises.get(scopeData.scopeStr);
|
||||
if (!existingPromise) {
|
||||
existingPromise = this.handleCodeResponse(scopeData);
|
||||
if (isSupportedEnvironment(callbackUri)) {
|
||||
existingPromise = this.handleCodeResponse(scopeData);
|
||||
} else {
|
||||
inputBox = vscode.window.createInputBox();
|
||||
existingPromise = this.handleCodeInputBox(inputBox, codeVerifier, scopeData);
|
||||
}
|
||||
this._codeExchangePromises.set(scopeData.scopeStr, existingPromise);
|
||||
}
|
||||
|
||||
@@ -659,13 +660,7 @@ export class AzureActiveDirectoryService {
|
||||
throw new Error('No available code verifier');
|
||||
}
|
||||
|
||||
const token = await this.exchangeCodeForToken(code, verifier, scopeData);
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
|
||||
const session = await this.convertToSession(token);
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
resolve(session);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
@@ -680,8 +675,33 @@ export class AzureActiveDirectoryService {
|
||||
});
|
||||
}
|
||||
|
||||
private async exchangeCodeForToken(code: string, codeVerifier: string, scopeData: IScopeData): Promise<IToken> {
|
||||
private async handleCodeInputBox(inputBox: vscode.InputBox, verifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.title = localize('pasteCodeTitle', 'Microsoft Authentication');
|
||||
inputBox.prompt = localize('pasteCodePrompt', 'Provide the authorization code to complete the sign in flow.');
|
||||
inputBox.placeholder = localize('pasteCodePlaceholder', 'Paste authorization code here...');
|
||||
return new Promise((resolve: (value: vscode.AuthenticationSession) => void, reject) => {
|
||||
inputBox.show();
|
||||
inputBox.onDidAccept(async () => {
|
||||
const code = inputBox.value;
|
||||
if (code) {
|
||||
inputBox.dispose();
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
resolve(session);
|
||||
}
|
||||
});
|
||||
inputBox.onDidHide(() => {
|
||||
if (!inputBox.value) {
|
||||
inputBox.dispose();
|
||||
reject('Cancelled');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async exchangeCodeForSession(code: string, codeVerifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
Logger.info(`Exchanging login code for token for scopes: ${scopeData.scopeStr}`);
|
||||
let token: IToken | undefined;
|
||||
try {
|
||||
const postData = querystring.stringify({
|
||||
grant_type: 'authorization_code',
|
||||
@@ -698,11 +718,18 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
const json = await this.fetchTokenResponse(endpoint, postData, scopeData);
|
||||
Logger.info(`Exchanging login code for token (for scopes: ${scopeData.scopeStr}) succeeded!`);
|
||||
return this.convertToTokenSync(json, scopeData);
|
||||
token = this.convertToTokenSync(json, scopeData);
|
||||
} catch (e) {
|
||||
Logger.error(`Error exchanging code for token (for scopes ${scopeData.scopeStr}): ${e}`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
|
||||
return await this.convertToSession(token);
|
||||
}
|
||||
|
||||
private async fetchTokenResponse(endpoint: string, postData: string, scopeData: IScopeData): Promise<ITokenResponse> {
|
||||
|
||||
@@ -2,7 +2,40 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { env, UIKind, Uri } from 'vscode';
|
||||
|
||||
export function toBase64UrlEncoding(base64string: string) {
|
||||
return base64string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); // Need to use base64url encoding
|
||||
}
|
||||
|
||||
const LOCALHOST_ADDRESSES = ['localhost', '127.0.0.1', '0:0:0:0:0:0:0:1', '::1'];
|
||||
function isLocalhost(uri: Uri): boolean {
|
||||
if (!/^https?$/i.test(uri.scheme)) {
|
||||
return false;
|
||||
}
|
||||
const host = uri.authority.split(':')[0];
|
||||
return LOCALHOST_ADDRESSES.indexOf(host) >= 0;
|
||||
}
|
||||
|
||||
export function isSupportedEnvironment(uri: Uri): boolean {
|
||||
if (env.uiKind === UIKind.Desktop) {
|
||||
return true;
|
||||
}
|
||||
// local development (localhost:* or 127.0.0.1:*)
|
||||
if (isLocalhost(uri)) {
|
||||
return true;
|
||||
}
|
||||
// At this point we should only ever see https
|
||||
if (uri.scheme !== 'https') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
// vscode.dev & insiders.vscode.dev
|
||||
/(?:^|\.)vscode\.dev$/.test(uri.authority) ||
|
||||
// github.dev & codespaces
|
||||
/(?:^|\.)github\.dev$/.test(uri.authority) ||
|
||||
// github.dev/codespaces local setup (github.localhost)
|
||||
/(?:^|\.)github\.localhost$/.test(uri.authority)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -298,6 +298,12 @@
|
||||
"tags": [
|
||||
"usesOnlineServices"
|
||||
]
|
||||
},
|
||||
"npm.scriptHover": {
|
||||
"type": "boolean",
|
||||
"description": "%config.npm.scriptHover%",
|
||||
"default": true,
|
||||
"scope": "window"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"config.npm.scriptExplorerExclude": "An array of regular expressions that indicate which scripts should be excluded from the NPM Scripts view.",
|
||||
"config.npm.enableRunFromFolder": "Enable running npm scripts contained in a folder from the Explorer context menu.",
|
||||
"config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.",
|
||||
"config.npm.scriptHover": "Display hover with 'Run' and 'Debug' commands for scripts.",
|
||||
"npm.parseError": "Npm task detection: failed to parse the file {0}",
|
||||
"taskdef.script": "The npm script to customize.",
|
||||
"taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.",
|
||||
|
||||
@@ -33,6 +33,7 @@ export function invalidateHoverScriptsCache(document?: TextDocument) {
|
||||
}
|
||||
|
||||
export class NpmScriptHoverProvider implements HoverProvider {
|
||||
private enabled: boolean;
|
||||
|
||||
constructor(private context: ExtensionContext) {
|
||||
context.subscriptions.push(commands.registerCommand('npm.runScriptFromHover', this.runScriptFromHover, this));
|
||||
@@ -40,9 +41,21 @@ export class NpmScriptHoverProvider implements HoverProvider {
|
||||
context.subscriptions.push(workspace.onDidChangeTextDocument((e) => {
|
||||
invalidateHoverScriptsCache(e.document);
|
||||
}));
|
||||
|
||||
const isEnabled = () => workspace.getConfiguration('npm').get<boolean>('scriptHover', true);
|
||||
this.enabled = isEnabled();
|
||||
context.subscriptions.push(workspace.onDidChangeConfiguration((e) => {
|
||||
if (e.affectsConfiguration('npm.scriptHover')) {
|
||||
this.enabled = isEnabled();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public provideHover(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult<Hover> {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
let hover: Hover | undefined = undefined;
|
||||
|
||||
if (!cachedDocument || cachedDocument.fsPath !== document.uri.fsPath) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MIT",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "4.7.3"
|
||||
"typescript": "^4.8.0-dev.20220801"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall.mjs"
|
||||
|
||||
@@ -11,3 +11,4 @@ cgmanifest.json
|
||||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
esbuild-preview.js
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.embedded", "source.groovy.embedded"],
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#6688cc"
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown",
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#D4D4D4"
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#FFFFFF"
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#000000ff"
|
||||
|
||||
@@ -60,7 +60,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.embedded", "source.groovy.embedded"],
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#d3af86"
|
||||
}
|
||||
|
||||
@@ -110,7 +110,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#F8F8F2"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#333333"
|
||||
|
||||
@@ -69,7 +69,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#F8F8F8"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#839496"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
{
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded"
|
||||
"source.groovy.embedded",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#657B83"
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
"editor.foreground": "#ffffff",
|
||||
"editor.selectionBackground": "#003f8e",
|
||||
"minimap.selectionHighlight": "#003f8e",
|
||||
"editor.lineHighlightBackground": "#00346e",
|
||||
"editorLineNumber.activeForeground": "#949494",
|
||||
"editor.lineHighlightBackground": "#00346e",
|
||||
"editorLineNumber.activeForeground": "#949494",
|
||||
"editorCursor.foreground": "#ffffff",
|
||||
"editorWhitespace.foreground": "#404f7d",
|
||||
"editorWidget.background": "#001c40",
|
||||
@@ -65,7 +65,12 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.embedded", "source.groovy.embedded", "meta.jsx.children"],
|
||||
"scope": [
|
||||
"meta.embedded",
|
||||
"source.groovy.embedded",
|
||||
"meta.jsx.children",
|
||||
"string meta.image.inline.markdown"
|
||||
],
|
||||
"settings": {
|
||||
//"background": "#002451",
|
||||
"foreground": "#FFFFFF"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
'use strict';
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const Terser = require('terser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const defaultConfig = require('../shared.webpack.config');
|
||||
const withBrowserDefaults = defaultConfig.browser;
|
||||
@@ -64,9 +66,12 @@ module.exports = withBrowserDefaults({
|
||||
{
|
||||
from: '../node_modules/typescript/lib/tsserver.js',
|
||||
to: 'typescript/tsserver.web.js',
|
||||
transform: (content) => {
|
||||
return Terser.minify(content.toString()).then(output => output.code);
|
||||
transform: async (content) => {
|
||||
const dynamicImportCompatPath = path.join(__dirname, '..', 'node_modules', 'typescript', 'lib', 'dynamicImportCompat.js');
|
||||
const prefix = fs.existsSync(dynamicImportCompatPath) ? fs.readFileSync(dynamicImportCompatPath) : undefined;
|
||||
const output = await Terser.minify(content.toString());
|
||||
|
||||
return prefix + '\n' + output.code;
|
||||
},
|
||||
transformPath: (targetPath) => {
|
||||
return targetPath.replace('tsserver.js', 'tsserver.web.js');
|
||||
|
||||
-1
@@ -190,7 +190,6 @@ export default class FileConfigurationManager extends Disposable {
|
||||
includeCompletionsWithSnippetText: config.get<boolean>('suggest.includeCompletionsWithSnippetText', true),
|
||||
includeCompletionsWithClassMemberSnippets: config.get<boolean>('suggest.classMemberSnippets.enabled', true),
|
||||
includeCompletionsWithObjectLiteralMethodSnippets: config.get<boolean>('suggest.objectLiteralMethodSnippets.enabled', true),
|
||||
// @ts-expect-error until TS 4.8
|
||||
autoImportFileExcludePatterns: this.getAutoImportFileExcludePatternsPreference(preferencesConfig, vscode.workspace.getWorkspaceFolder(document.uri)?.uri),
|
||||
useLabelDetailsInCompletionEntries: true,
|
||||
allowIncompleteCompletions: true,
|
||||
|
||||
@@ -11,6 +11,7 @@ import { coalesce } from '../utils/arrays';
|
||||
import { Delayer, setImmediate } from '../utils/async';
|
||||
import { nulToken } from '../utils/cancellation';
|
||||
import { Disposable } from '../utils/dispose';
|
||||
import { vscodeNotebookCell } from '../utils/fileSchemes';
|
||||
import * as languageModeIds from '../utils/languageIds';
|
||||
import { ResourceMap } from '../utils/resourceMap';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
@@ -361,6 +362,98 @@ class GetErrRequest {
|
||||
}
|
||||
}
|
||||
|
||||
class TabResourceTracker extends Disposable {
|
||||
|
||||
private readonly _onDidChange = this._register(new vscode.EventEmitter<{
|
||||
readonly closed: Iterable<vscode.Uri>;
|
||||
readonly opened: Iterable<vscode.Uri>;
|
||||
}>());
|
||||
public readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private readonly _tabResources: ResourceMap<{ readonly tabs: Set<vscode.Tab> }>;
|
||||
|
||||
constructor(
|
||||
normalizePath: (resource: vscode.Uri) => string | undefined,
|
||||
config: {
|
||||
readonly onCaseInsensitiveFileSystem: boolean;
|
||||
},
|
||||
) {
|
||||
super();
|
||||
|
||||
this._tabResources = new ResourceMap<{ readonly tabs: Set<vscode.Tab> }>(normalizePath, config);
|
||||
|
||||
for (const tabGroup of vscode.window.tabGroups.all) {
|
||||
for (const tab of tabGroup.tabs) {
|
||||
this.add(tab);
|
||||
}
|
||||
}
|
||||
|
||||
this._register(vscode.window.tabGroups.onDidChangeTabs(e => {
|
||||
const closed = e.closed.flatMap(tab => this.delete(tab));
|
||||
const opened = e.opened.flatMap(tab => this.add(tab));
|
||||
if (closed.length || opened.length) {
|
||||
this._onDidChange.fire({ closed, opened });
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public has(resource: vscode.Uri): boolean {
|
||||
if (resource.scheme === vscodeNotebookCell) {
|
||||
const notebook = vscode.workspace.notebookDocuments.find(doc =>
|
||||
doc.getCells().some(cell => cell.document.uri.toString() === resource.toString()));
|
||||
|
||||
return !!notebook && this.has(notebook.uri);
|
||||
}
|
||||
|
||||
const entry = this._tabResources.get(resource);
|
||||
return !!entry && entry.tabs.size > 0;
|
||||
}
|
||||
|
||||
private add(tab: vscode.Tab): vscode.Uri[] {
|
||||
const addedResources: vscode.Uri[] = [];
|
||||
for (const uri of this.getResourcesForTab(tab)) {
|
||||
const entry = this._tabResources.get(uri);
|
||||
if (entry) {
|
||||
entry.tabs.add(tab);
|
||||
} else {
|
||||
this._tabResources.set(uri, { tabs: new Set([tab]) });
|
||||
addedResources.push(uri);
|
||||
}
|
||||
}
|
||||
return addedResources;
|
||||
}
|
||||
|
||||
private delete(tab: vscode.Tab): vscode.Uri[] {
|
||||
const closedResources: vscode.Uri[] = [];
|
||||
for (const uri of this.getResourcesForTab(tab)) {
|
||||
const entry = this._tabResources.get(uri);
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.tabs.delete(tab);
|
||||
if (entry.tabs.size === 0) {
|
||||
this._tabResources.delete(uri);
|
||||
closedResources.push(uri);
|
||||
}
|
||||
}
|
||||
return closedResources;
|
||||
}
|
||||
|
||||
private getResourcesForTab(tab: vscode.Tab): vscode.Uri[] {
|
||||
if (tab.input instanceof vscode.TabInputText) {
|
||||
return [tab.input.uri];
|
||||
} else if (tab.input instanceof vscode.TabInputTextDiff) {
|
||||
return [tab.input.original, tab.input.modified];
|
||||
} else if (tab.input instanceof vscode.TabInputNotebook) {
|
||||
return [tab.input.uri];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default class BufferSyncSupport extends Disposable {
|
||||
|
||||
private readonly client: ITypeScriptServiceClient;
|
||||
@@ -375,6 +468,8 @@ export default class BufferSyncSupport extends Disposable {
|
||||
private listening: boolean = false;
|
||||
private readonly synchronizer: BufferSynchronizer;
|
||||
|
||||
private readonly _tabResources: TabResourceTracker;
|
||||
|
||||
constructor(
|
||||
client: ITypeScriptServiceClient,
|
||||
modeIds: readonly string[],
|
||||
@@ -391,6 +486,28 @@ export default class BufferSyncSupport extends Disposable {
|
||||
this.pendingDiagnostics = new PendingDiagnostics(pathNormalizer, { onCaseInsensitiveFileSystem });
|
||||
this.synchronizer = new BufferSynchronizer(client, pathNormalizer, onCaseInsensitiveFileSystem);
|
||||
|
||||
this._tabResources = this._register(new TabResourceTracker(pathNormalizer, { onCaseInsensitiveFileSystem }));
|
||||
this._register(this._tabResources.onDidChange(e => {
|
||||
if (this.client.configuration.enableProjectDiagnostics) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const closed of e.closed) {
|
||||
const syncedBuffer = this.syncedBuffers.get(closed);
|
||||
if (syncedBuffer) {
|
||||
this.pendingDiagnostics.delete(closed);
|
||||
this.pendingGetErr?.files.delete(closed);
|
||||
}
|
||||
}
|
||||
|
||||
for (const opened of e.opened) {
|
||||
const syncedBuffer = this.syncedBuffers.get(opened);
|
||||
if (syncedBuffer) {
|
||||
this.requestDiagnostic(syncedBuffer);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.updateConfiguration();
|
||||
vscode.workspace.onDidChangeConfiguration(this.updateConfiguration, this, this._disposables);
|
||||
}
|
||||
@@ -494,6 +611,7 @@ export default class BufferSyncSupport extends Disposable {
|
||||
if (!syncedBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pendingDiagnostics.delete(resource);
|
||||
this.pendingGetErr?.files.delete(resource);
|
||||
this.syncedBuffers.delete(resource);
|
||||
@@ -506,7 +624,7 @@ export default class BufferSyncSupport extends Disposable {
|
||||
|
||||
public interruptGetErr<R>(f: () => R): R {
|
||||
if (!this.pendingGetErr
|
||||
|| this.client.configuration.enableProjectDiagnostics // `geterr` happens on seperate server so no need to cancel it.
|
||||
|| this.client.configuration.enableProjectDiagnostics // `geterr` happens on separate server so no need to cancel it.
|
||||
) {
|
||||
return f();
|
||||
}
|
||||
@@ -628,7 +746,11 @@ export default class BufferSyncSupport extends Disposable {
|
||||
this._validateTypeScript = tsConfig.get<boolean>('validate.enable', true);
|
||||
}
|
||||
|
||||
private shouldValidate(buffer: SyncedBuffer) {
|
||||
private shouldValidate(buffer: SyncedBuffer): boolean {
|
||||
if (!this.client.configuration.enableProjectDiagnostics && !this._tabResources.has(buffer.resource)) { // Only validate resources that are showing to the user
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (buffer.kind) {
|
||||
case BufferKind.JavaScript:
|
||||
return this._validateJavaScript;
|
||||
|
||||
@@ -25,7 +25,7 @@ import * as fileSchemes from './utils/fileSchemes';
|
||||
import { Logger } from './utils/logger';
|
||||
import { isWeb } from './utils/platform';
|
||||
import { TypeScriptPluginPathsProvider } from './utils/pluginPathsProvider';
|
||||
import { PluginManager } from './utils/plugins';
|
||||
import { PluginManager, TypeScriptServerPlugin } from './utils/plugins';
|
||||
import { TelemetryProperties, TelemetryReporter, VSCodeTelemetryReporter } from './utils/telemetry';
|
||||
import Tracer from './utils/tracer';
|
||||
import { inferredProjectCompilerOptions, ProjectType } from './utils/tsconfig';
|
||||
@@ -430,32 +430,29 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
});
|
||||
|
||||
handle.onExit((data: TypeScriptServerExitEvent) => {
|
||||
const { code, signal } = data;
|
||||
this.error(`TSServer exited. Code: ${code}. Signal: ${signal}`);
|
||||
|
||||
// In practice, the exit code is an integer with no ties to any identity,
|
||||
// so it can be classified as SystemMetaData, rather than CallstackOrException.
|
||||
/* __GDPR__
|
||||
"tsserver.exitWithCode" : {
|
||||
"owner": "mjbvz",
|
||||
"code" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"signal" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.exitWithCode', { code: code ?? undefined, signal: signal ?? undefined });
|
||||
|
||||
|
||||
if (this.token !== mytoken) {
|
||||
// this is coming from an old process
|
||||
return;
|
||||
}
|
||||
|
||||
const { code, signal } = data;
|
||||
|
||||
if (code === null || typeof code === 'undefined') {
|
||||
this.info(`TSServer exited. Signal: ${signal}`);
|
||||
} else {
|
||||
// In practice, the exit code is an integer with no ties to any identity,
|
||||
// so it can be classified as SystemMetaData, rather than CallstackOrException.
|
||||
this.error(`TSServer exited with code: ${code}. Signal: ${signal}`);
|
||||
/* __GDPR__
|
||||
"tsserver.exitWithCode" : {
|
||||
"owner": "mjbvz",
|
||||
"code" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"signal" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.exitWithCode', { code, signal: signal ?? undefined });
|
||||
}
|
||||
|
||||
if (handle.tsServerLogFile) {
|
||||
this.info(`TSServer log file: ${handle.tsServerLogFile}`);
|
||||
}
|
||||
@@ -587,6 +584,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
this.numberRestarts++;
|
||||
let startService = true;
|
||||
|
||||
const pluginExtensionList = this.pluginManager.plugins.map(plugin => plugin.extension.id).join(', ');
|
||||
const reportIssueItem: vscode.MessageItem = {
|
||||
title: localize('serverDiedReportIssue', 'Report Issue'),
|
||||
};
|
||||
@@ -599,7 +597,9 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
startService = false;
|
||||
this.hasServerFatallyCrashedTooManyTimes = true;
|
||||
prompt = vscode.window.showErrorMessage(
|
||||
localize('serverDiedAfterStart', 'The TypeScript language service died 5 times right after it got started. The service will not be restarted.'),
|
||||
this.pluginManager.plugins.length
|
||||
? localize('serverDiedImmediatelyWithPlugins', "The JS/TS language service immediately crashed 5 times. The service will not be restarted.\nThis may be caused by a plugin contributed by one of these extensions: {0}", pluginExtensionList)
|
||||
: localize('serverDiedImmediately', "The JS/TS language service immediately crashed 5 times. The service will not be restarted."),
|
||||
reportIssueItem);
|
||||
|
||||
/* __GDPR__
|
||||
@@ -613,21 +613,30 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
this.logTelemetry('serviceExited');
|
||||
} else if (diff < 60 * 1000 * 5 /* 5 Minutes */) {
|
||||
this.lastStart = Date.now();
|
||||
prompt = vscode.window.showWarningMessage(
|
||||
localize('serverDied', 'The TypeScript language service died unexpectedly 5 times in the last 5 Minutes.'),
|
||||
reportIssueItem);
|
||||
if (!this._isPromptingAfterCrash) {
|
||||
prompt = vscode.window.showWarningMessage(
|
||||
this.pluginManager.plugins.length
|
||||
? localize('serverDiedFiveTimesWithPlugins', "The JS/TS language service crashed 5 times in the last 5 Minutes.\nThis may be caused by a plugin contributed by one of these extensions: {0}", pluginExtensionList)
|
||||
: localize('serverDiedFiveTimes', "The JS/TS language service crashed 5 times in the last 5 Minutes."),
|
||||
reportIssueItem);
|
||||
}
|
||||
}
|
||||
} else if (['vscode-insiders', 'code-oss'].includes(vscode.env.uriScheme)) {
|
||||
// Prompt after a single restart
|
||||
if (!this._isPromptingAfterCrash && previousState.type === ServerState.Type.Errored && previousState.error instanceof TypeScriptServerError) {
|
||||
this.numberRestarts = 0;
|
||||
this._isPromptingAfterCrash = true;
|
||||
this.numberRestarts = 0;
|
||||
if (!this._isPromptingAfterCrash) {
|
||||
prompt = vscode.window.showWarningMessage(
|
||||
localize('serverDiedOnce', 'The TypeScript language service died unexpectedly.'),
|
||||
this.pluginManager.plugins.length
|
||||
? localize('serverDiedOnceWithPlugins', "The JS/TS language service crashed.\nThis may be caused by a plugin contributed by one of these extensions: {0}", pluginExtensionList)
|
||||
: localize('serverDiedOnce', "The JS/TS language service crashed."),
|
||||
reportIssueItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (prompt) {
|
||||
this._isPromptingAfterCrash = true;
|
||||
}
|
||||
|
||||
prompt?.then(item => {
|
||||
this._isPromptingAfterCrash = false;
|
||||
|
||||
@@ -647,7 +656,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
});
|
||||
} else {
|
||||
const args = previousState.type === ServerState.Type.Errored && previousState.error instanceof TypeScriptServerError
|
||||
? getReportIssueArgsForError(previousState.error, previousState.tsServerLogFile)
|
||||
? getReportIssueArgsForError(previousState.error, previousState.tsServerLogFile, this.pluginManager.plugins)
|
||||
: undefined;
|
||||
vscode.commands.executeCommand('workbench.action.openIssueReporter', args);
|
||||
}
|
||||
@@ -1005,6 +1014,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
function getReportIssueArgsForError(
|
||||
error: TypeScriptServerError,
|
||||
logPath: string | undefined,
|
||||
globalPlugins: readonly TypeScriptServerPlugin[],
|
||||
): { extensionId: string; issueTitle: string; issueBody: string } | undefined {
|
||||
if (!error.serverStack || !error.serverMessage) {
|
||||
return undefined;
|
||||
@@ -1023,6 +1033,10 @@ function getReportIssueArgsForError(
|
||||
3.`,
|
||||
];
|
||||
|
||||
if (globalPlugins.length) {
|
||||
sections.push(`**Global TS Server Plugins**\n\n` + globalPlugins.map(plugin => `- \`${plugin.name}\``).join('\n'));
|
||||
}
|
||||
|
||||
if (logPath) {
|
||||
sections.push(`**TS Server Log**
|
||||
|
||||
@@ -1036,7 +1050,7 @@ The log file may contain personal data, including full paths and source code fro
|
||||
|
||||
sections.push(`**TS Server Log**
|
||||
|
||||
❗️Server logging disabled. To help us fix crashes like this, please enable logging by setting:
|
||||
❗️ Server logging disabled. To help us fix crashes like this, please enable logging by setting:
|
||||
|
||||
\`\`\`json
|
||||
"typescript.tsserver.log": "verbose"
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as arrays from './arrays';
|
||||
import { Disposable } from './dispose';
|
||||
|
||||
export interface TypeScriptServerPlugin {
|
||||
readonly extension: vscode.Extension<unknown>;
|
||||
readonly uri: vscode.Uri;
|
||||
readonly name: string;
|
||||
readonly enableForWorkspaceTypeScriptVersions: boolean;
|
||||
@@ -74,6 +75,7 @@ export class PluginManager extends Disposable {
|
||||
const plugins: TypeScriptServerPlugin[] = [];
|
||||
for (const plugin of pack.contributes.typescriptServerPlugins) {
|
||||
plugins.push({
|
||||
extension,
|
||||
name: plugin.name,
|
||||
enableForWorkspaceTypeScriptVersions: !!plugin.enableForWorkspaceTypeScriptVersions,
|
||||
uri: extension.extensionUri,
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as assert from 'assert';
|
||||
import 'mocha';
|
||||
import * as vscode from 'vscode';
|
||||
import { disposeAll } from '../utils';
|
||||
import { Kernel, saveAllFilesAndCloseAll } from './notebook.test';
|
||||
import { Kernel, saveAllFilesAndCloseAll } from './notebook.api.test';
|
||||
|
||||
export type INativeInteractiveWindow = { notebookUri: vscode.Uri; inputUri: vscode.Uri; notebookEditor: vscode.NotebookEditor };
|
||||
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'mocha';
|
||||
import { TextDecoder, TextEncoder } from 'util';
|
||||
import * as vscode from 'vscode';
|
||||
import { asPromise, assertNoRpc, closeAllEditors, createRandomFile, disposeAll, revertAllDirty, saveAllEditors } from '../utils';
|
||||
|
||||
async function createRandomNotebookFile() {
|
||||
return createRandomFile('', undefined, '.vsctestnb');
|
||||
}
|
||||
|
||||
async function openRandomNotebookDocument() {
|
||||
const uri = await createRandomNotebookFile();
|
||||
return vscode.workspace.openNotebookDocument(uri);
|
||||
}
|
||||
|
||||
export async function saveAllFilesAndCloseAll() {
|
||||
await saveAllEditors();
|
||||
await closeAllEditors();
|
||||
}
|
||||
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export class Kernel {
|
||||
|
||||
readonly controller: vscode.NotebookController;
|
||||
|
||||
readonly associatedNotebooks = new Set<string>();
|
||||
|
||||
constructor(id: string, label: string, viewType: string = 'notebookCoreTest') {
|
||||
this.controller = vscode.notebooks.createNotebookController(id, viewType, label);
|
||||
this.controller.executeHandler = this._execute.bind(this);
|
||||
this.controller.supportsExecutionOrder = true;
|
||||
this.controller.supportedLanguages = ['typescript', 'javascript'];
|
||||
this.controller.onDidChangeSelectedNotebooks(e => {
|
||||
if (e.selected) {
|
||||
this.associatedNotebooks.add(e.notebook.uri.toString());
|
||||
} else {
|
||||
this.associatedNotebooks.delete(e.notebook.uri.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected async _execute(cells: vscode.NotebookCell[]): Promise<void> {
|
||||
for (const cell of cells) {
|
||||
await this._runCell(cell);
|
||||
}
|
||||
}
|
||||
|
||||
protected async _runCell(cell: vscode.NotebookCell) {
|
||||
// create a single output with exec order 1 and output is plain/text
|
||||
// of either the cell itself or (iff empty) the cell's document's uri
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start(Date.now());
|
||||
task.executionOrder = 1;
|
||||
await sleep(10); // Force to be take some time
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text(cell.document.getText() || cell.document.uri.toString(), 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getFocusedCell(editor?: vscode.NotebookEditor) {
|
||||
return editor ? editor.notebook.cellAt(editor.selections[0].start) : undefined;
|
||||
}
|
||||
|
||||
const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||
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: [
|
||||
{
|
||||
value: 'test',
|
||||
languageId: 'typescript',
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
outputs: [],
|
||||
metadata: { custom: { testCellMetadata: 123 } },
|
||||
executionSummary: { timing: { startTime: 10, endTime: 20 } }
|
||||
},
|
||||
{
|
||||
value: 'test2',
|
||||
languageId: 'typescript',
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
outputs: [
|
||||
new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('Hello World', 'text/plain')
|
||||
],
|
||||
{
|
||||
testOutputMetadata: true,
|
||||
['text/plain']: { testOutputItemMetadata: true }
|
||||
})
|
||||
],
|
||||
executionSummary: { executionOrder: 5, success: true },
|
||||
metadata: { custom: { testCellMetadata: 456 } }
|
||||
}
|
||||
]
|
||||
};
|
||||
return dto;
|
||||
},
|
||||
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: () => { }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
(vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('Notebook API tests', function () {
|
||||
|
||||
const testDisposables: vscode.Disposable[] = [];
|
||||
const suiteDisposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
|
||||
assertNoRpc();
|
||||
|
||||
await revertAllDirty();
|
||||
await closeAllEditors();
|
||||
|
||||
disposeAll(suiteDisposables);
|
||||
suiteDisposables.length = 0;
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
|
||||
});
|
||||
|
||||
let defaultKernel: Kernel;
|
||||
|
||||
setup(async function () {
|
||||
// there should be ONE default kernel in this suite
|
||||
defaultKernel = new Kernel('mainKernel', 'Notebook Default Kernel');
|
||||
testDisposables.push(defaultKernel.controller);
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
teardown(async function () {
|
||||
disposeAll(testDisposables);
|
||||
testDisposables.length = 0;
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
test('notebook open', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||
|
||||
const secondCell = editor.notebook.cellAt(1);
|
||||
assert.strictEqual(secondCell.outputs.length, 1);
|
||||
assert.deepStrictEqual(secondCell.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
|
||||
assert.strictEqual(secondCell.outputs[0].items.length, 1);
|
||||
assert.strictEqual(secondCell.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.strictEqual(new TextDecoder().decode(secondCell.outputs[0].items[0].data), 'Hello World');
|
||||
assert.strictEqual(secondCell.executionSummary?.executionOrder, 5);
|
||||
assert.strictEqual(secondCell.executionSummary?.success, true);
|
||||
});
|
||||
|
||||
test('multiple tabs: different editors with same document', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const firstNotebookEditor = await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.One });
|
||||
const secondNotebookEditor = await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.notStrictEqual(firstNotebookEditor, secondNotebookEditor);
|
||||
assert.strictEqual(firstNotebookEditor?.notebook, secondNotebookEditor?.notebook, 'split notebook editors share the same document');
|
||||
});
|
||||
|
||||
test.skip('#106657. Opening a notebook from markers view is broken ', async function () {
|
||||
|
||||
const document = await openRandomNotebookDocument();
|
||||
const [cell] = document.getCells();
|
||||
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor, undefined);
|
||||
|
||||
// opening a cell-uri opens a notebook editor
|
||||
await vscode.window.showTextDocument(cell.document, { viewColumn: vscode.ViewColumn.Active });
|
||||
// await vscode.commands.executeCommand('vscode.open', cell.document.uri, vscode.ViewColumn.Active);
|
||||
|
||||
assert.strictEqual(!!vscode.window.activeNotebookEditor, true);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.uri.toString(), document.uri.toString());
|
||||
});
|
||||
|
||||
test('Cannot open notebook from cell-uri with vscode.open-command', async function () {
|
||||
|
||||
const document = await openRandomNotebookDocument();
|
||||
const [cell] = document.getCells();
|
||||
|
||||
await saveAllFilesAndCloseAll();
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor, undefined);
|
||||
|
||||
// BUG is that the editor opener (https://github.com/microsoft/vscode/blob/8e7877bdc442f1e83a7fec51920d82b696139129/src/vs/editor/browser/services/openerService.ts#L69)
|
||||
// removes the fragment if it matches something numeric. For notebooks that's not wanted...
|
||||
// opening a cell-uri opens a notebook editor
|
||||
await vscode.commands.executeCommand('vscode.open', cell.document.uri);
|
||||
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.uri.toString(), document.uri.toString());
|
||||
});
|
||||
|
||||
test('#97830, #97764. Support switch to other editor types', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const focusedCell = getFocusedCell(editor);
|
||||
assert.ok(focusedCell);
|
||||
edit.replace(focusedCell.document.uri, focusedCell.document.lineAt(0).range, 'var abc = 0;');
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'var abc = 0;');
|
||||
|
||||
// no kernel -> no default language
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||
|
||||
await vscode.commands.executeCommand('vscode.openWith', notebook.uri, 'default');
|
||||
assert.strictEqual(vscode.window.activeTextEditor?.document.uri.path, notebook.uri.path);
|
||||
});
|
||||
|
||||
test('#102411 - untitled notebook creation failed', async function () {
|
||||
await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { viewType: 'notebookCoreTest' });
|
||||
assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'untitled notebook editor is not undefined');
|
||||
|
||||
await closeAllEditors();
|
||||
});
|
||||
|
||||
test('#115855 onDidSaveNotebookDocument', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
const notebook = await vscode.workspace.openNotebookDocument(resource);
|
||||
|
||||
const notebookEdit = new vscode.NotebookEdit(new vscode.NotebookRange(1, 1), [new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'test 2', 'javascript')]);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(notebook.uri, [notebookEdit]);
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(notebook.isDirty, true);
|
||||
|
||||
const saveEvent = asPromise(vscode.workspace.onDidSaveNotebookDocument);
|
||||
await notebook.save();
|
||||
await saveEvent;
|
||||
|
||||
assert.strictEqual(notebook.isDirty, false);
|
||||
});
|
||||
});
|
||||
|
||||
(vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('statusbar', () => {
|
||||
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
|
||||
const onDidCallProvide = emitter.event;
|
||||
const suiteDisposables: vscode.Disposable[] = [];
|
||||
suiteTeardown(async function () {
|
||||
assertNoRpc();
|
||||
|
||||
await revertAllDirty();
|
||||
await closeAllEditors();
|
||||
|
||||
disposeAll(suiteDisposables);
|
||||
suiteDisposables.length = 0;
|
||||
});
|
||||
|
||||
suiteSetup(() => {
|
||||
suiteDisposables.push(vscode.notebooks.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
|
||||
async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
|
||||
emitter.fire(cell);
|
||||
return [];
|
||||
}
|
||||
}));
|
||||
|
||||
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
|
||||
});
|
||||
|
||||
test('provideCellStatusBarItems called on metadata change', async function () {
|
||||
const provideCalled = asPromise(onDidCallProvide);
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
await provideCalled;
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellMetadata(notebook.uri, 0, { inputCollapsed: true });
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
await provideCalled;
|
||||
});
|
||||
});
|
||||
|
||||
suite('Notebook & LiveShare', function () {
|
||||
|
||||
const suiteDisposables: vscode.Disposable[] = [];
|
||||
const notebookType = 'vsls-testing';
|
||||
|
||||
suiteTeardown(() => {
|
||||
vscode.Disposable.from(...suiteDisposables).dispose();
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
|
||||
suiteDisposables.push(vscode.workspace.registerNotebookSerializer(notebookType, new class implements vscode.NotebookSerializer {
|
||||
deserializeNotebook(content: Uint8Array, _token: vscode.CancellationToken): vscode.NotebookData | Thenable<vscode.NotebookData> {
|
||||
const value = new TextDecoder().decode(content);
|
||||
const cell1 = new vscode.NotebookCellData(vscode.NotebookCellKind.Code, value, 'fooLang');
|
||||
cell1.outputs = [new vscode.NotebookCellOutput([vscode.NotebookCellOutputItem.stderr(value)])];
|
||||
return new vscode.NotebookData([cell1]);
|
||||
}
|
||||
serializeNotebook(data: vscode.NotebookData, _token: vscode.CancellationToken): Uint8Array | Thenable<Uint8Array> {
|
||||
return new TextEncoder().encode(data.cells[0].value);
|
||||
}
|
||||
}, {}, {
|
||||
displayName: 'LS',
|
||||
filenamePattern: ['*'],
|
||||
}));
|
||||
});
|
||||
|
||||
test('command: vscode.resolveNotebookContentProviders', async function () {
|
||||
|
||||
type Info = { viewType: string; displayName: string; filenamePattern: string[] };
|
||||
|
||||
const info = await vscode.commands.executeCommand<Info[]>('vscode.resolveNotebookContentProviders');
|
||||
assert.strictEqual(Array.isArray(info), true);
|
||||
|
||||
const item = info.find(item => item.viewType === notebookType);
|
||||
assert.ok(item);
|
||||
assert.strictEqual(item?.viewType, notebookType);
|
||||
});
|
||||
|
||||
test('command: vscode.executeDataToNotebook', async function () {
|
||||
const value = 'dataToNotebook';
|
||||
const data = await vscode.commands.executeCommand<vscode.NotebookData>('vscode.executeDataToNotebook', notebookType, new TextEncoder().encode(value));
|
||||
assert.ok(data instanceof vscode.NotebookData);
|
||||
assert.strictEqual(data.cells.length, 1);
|
||||
assert.strictEqual(data.cells[0].value, value);
|
||||
assert.strictEqual(new TextDecoder().decode(data.cells[0].outputs![0].items[0].data), value);
|
||||
});
|
||||
|
||||
test('command: vscode.executeNotebookToData', async function () {
|
||||
const value = 'notebookToData';
|
||||
const notebook = new vscode.NotebookData([new vscode.NotebookCellData(vscode.NotebookCellKind.Code, value, 'fooLang')]);
|
||||
const data = await vscode.commands.executeCommand<Uint8Array>('vscode.executeNotebookToData', notebookType, notebook);
|
||||
assert.ok(data instanceof Uint8Array);
|
||||
assert.deepStrictEqual(new TextDecoder().decode(data), value);
|
||||
});
|
||||
});
|
||||
@@ -7,7 +7,7 @@ import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import * as utils from '../utils';
|
||||
|
||||
suite.skip('Notebook Document', function () {
|
||||
suite('Notebook Document', function () {
|
||||
|
||||
const simpleContentProvider = new class implements vscode.NotebookSerializer {
|
||||
deserializeNotebook(_data: Uint8Array): vscode.NotebookData | Thenable<vscode.NotebookData> {
|
||||
@@ -315,6 +315,18 @@ suite.skip('Notebook Document', function () {
|
||||
assert.strictEqual(data.cellChanges[0].cell.index, 0);
|
||||
});
|
||||
|
||||
test('workspace edit API (notebookMetadata)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.workspace.openNotebookDocument(uri);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const metdataEdit = vscode.NotebookEdit.updateNotebookMetadata({ ...document.metadata, custom: { ...(document.metadata.custom || {}), extraNotebookMetadata: true } });
|
||||
edit.set(document.uri, [metdataEdit]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.equal(success, true);
|
||||
assert.ok(document.metadata.custom.extraNotebookMetadata, `Test metadata not found`);
|
||||
});
|
||||
|
||||
test('document save API', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const notebook = await vscode.workspace.openNotebookDocument(uri);
|
||||
@@ -411,7 +423,7 @@ suite.skip('Notebook Document', function () {
|
||||
assert.strictEqual(document.isDirty, false);
|
||||
});
|
||||
|
||||
test('onDidOpenNotebookDocument - emit event only once when opened in two editors', async function () {
|
||||
test.skip('onDidOpenNotebookDocument - emit event only once when opened in two editors', async function () { // TODO@rebornix https://github.com/microsoft/vscode/issues/157222
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
let counter = 0;
|
||||
testDisposables.push(vscode.workspace.onDidOpenNotebookDocument(nb => {
|
||||
|
||||
@@ -65,39 +65,6 @@ import * as utils from '../utils';
|
||||
testDisposables.length = 0;
|
||||
});
|
||||
|
||||
test.skip('showNotebookDocument', async function () { // TODO@rebornix https://github.com/microsoft/vscode/issues/139078
|
||||
|
||||
const notebookDocumentsFromOnDidOpen = new Set<vscode.NotebookDocument>();
|
||||
const sub = vscode.workspace.onDidOpenNotebookDocument(e => {
|
||||
notebookDocumentsFromOnDidOpen.add(e);
|
||||
});
|
||||
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const editor = await vscode.window.showNotebookDocument(uri);
|
||||
assert.strictEqual(uri.toString(), editor.notebook.uri.toString());
|
||||
|
||||
assert.strictEqual(notebookDocumentsFromOnDidOpen.has(editor.notebook), true);
|
||||
|
||||
const includes = vscode.workspace.notebookDocuments.includes(editor.notebook);
|
||||
assert.strictEqual(true, includes);
|
||||
|
||||
sub.dispose();
|
||||
});
|
||||
|
||||
// TODO@rebornix deal with getting started
|
||||
test.skip('notebook editor has viewColumn', async function () {
|
||||
|
||||
const uri1 = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const editor1 = await vscode.window.showNotebookDocument(uri1);
|
||||
|
||||
assert.strictEqual(editor1.viewColumn, vscode.ViewColumn.One);
|
||||
|
||||
const uri2 = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const editor2 = await vscode.window.showNotebookDocument(uri2, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(editor2.viewColumn, vscode.ViewColumn.Two);
|
||||
});
|
||||
|
||||
// #138683
|
||||
test('Opening a notebook should fire activeNotebook event changed only once', async function () {
|
||||
const openedEditor = onDidOpenNotebookEditor();
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'mocha';
|
||||
import { TextDecoder } from 'util';
|
||||
import * as vscode from 'vscode';
|
||||
import { asPromise, assertNoRpc, closeAllEditors, createRandomFile, DeferredPromise, disposeAll, revertAllDirty, saveAllEditors } from '../utils';
|
||||
|
||||
async function createRandomNotebookFile() {
|
||||
return createRandomFile('', undefined, '.vsctestnb');
|
||||
}
|
||||
|
||||
async function openRandomNotebookDocument() {
|
||||
const uri = await createRandomNotebookFile();
|
||||
return vscode.workspace.openNotebookDocument(uri);
|
||||
}
|
||||
|
||||
export async function saveAllFilesAndCloseAll() {
|
||||
await saveAllEditors();
|
||||
await closeAllEditors();
|
||||
}
|
||||
|
||||
async function withEvent<T>(event: vscode.Event<T>, callback: (e: Promise<T>) => Promise<void>) {
|
||||
const e = asPromise<T>(event);
|
||||
await callback(e);
|
||||
}
|
||||
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export class Kernel {
|
||||
|
||||
readonly controller: vscode.NotebookController;
|
||||
|
||||
readonly associatedNotebooks = new Set<string>();
|
||||
|
||||
constructor(id: string, label: string, viewType: string = 'notebookCoreTest') {
|
||||
this.controller = vscode.notebooks.createNotebookController(id, viewType, label);
|
||||
this.controller.executeHandler = this._execute.bind(this);
|
||||
this.controller.supportsExecutionOrder = true;
|
||||
this.controller.supportedLanguages = ['typescript', 'javascript'];
|
||||
this.controller.onDidChangeSelectedNotebooks(e => {
|
||||
if (e.selected) {
|
||||
this.associatedNotebooks.add(e.notebook.uri.toString());
|
||||
} else {
|
||||
this.associatedNotebooks.delete(e.notebook.uri.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected async _execute(cells: vscode.NotebookCell[]): Promise<void> {
|
||||
for (const cell of cells) {
|
||||
await this._runCell(cell);
|
||||
}
|
||||
}
|
||||
|
||||
protected async _runCell(cell: vscode.NotebookCell) {
|
||||
// create a single output with exec order 1 and output is plain/text
|
||||
// of either the cell itself or (iff empty) the cell's document's uri
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start(Date.now());
|
||||
task.executionOrder = 1;
|
||||
await sleep(10); // Force to be take some time
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text(cell.document.getText() || cell.document.uri.toString(), 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function assertKernel(kernel: Kernel, notebook: vscode.NotebookDocument): Promise<void> {
|
||||
const success = await vscode.commands.executeCommand('notebook.selectKernel', {
|
||||
extension: 'vscode.vscode-api-tests',
|
||||
id: kernel.controller.id
|
||||
});
|
||||
assert.ok(success, `expected selected kernel to be ${kernel.controller.id}`);
|
||||
assert.ok(kernel.associatedNotebooks.has(notebook.uri.toString()));
|
||||
}
|
||||
|
||||
const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||
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: [
|
||||
{
|
||||
value: 'test',
|
||||
languageId: 'typescript',
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
outputs: [],
|
||||
metadata: { custom: { testCellMetadata: 123 } },
|
||||
executionSummary: { timing: { startTime: 10, endTime: 20 } }
|
||||
},
|
||||
{
|
||||
value: 'test2',
|
||||
languageId: 'typescript',
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
outputs: [
|
||||
new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('Hello World', 'text/plain')
|
||||
],
|
||||
{
|
||||
testOutputMetadata: true,
|
||||
['text/plain']: { testOutputItemMetadata: true }
|
||||
})
|
||||
],
|
||||
executionSummary: { executionOrder: 5, success: true },
|
||||
metadata: { custom: { testCellMetadata: 456 } }
|
||||
}
|
||||
]
|
||||
};
|
||||
return dto;
|
||||
},
|
||||
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: () => { }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
(vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('Notebook Kernel API tests', function () {
|
||||
|
||||
const testDisposables: vscode.Disposable[] = [];
|
||||
const suiteDisposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
|
||||
assertNoRpc();
|
||||
|
||||
await revertAllDirty();
|
||||
await closeAllEditors();
|
||||
|
||||
disposeAll(suiteDisposables);
|
||||
suiteDisposables.length = 0;
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
|
||||
});
|
||||
|
||||
let defaultKernel: Kernel;
|
||||
|
||||
setup(async function () {
|
||||
// there should be ONE default kernel in this suite
|
||||
defaultKernel = new Kernel('mainKernel', 'Notebook Default Kernel');
|
||||
testDisposables.push(defaultKernel.controller);
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
teardown(async function () {
|
||||
disposeAll(testDisposables);
|
||||
testDisposables.length = 0;
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
test('cell execute command takes arguments', async () => {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
const cell = editor.notebook.cellAt(0);
|
||||
|
||||
await withEvent(vscode.workspace.onDidChangeNotebookDocument, async event => {
|
||||
await vscode.commands.executeCommand('notebook.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
});
|
||||
|
||||
await withEvent(vscode.workspace.onDidChangeNotebookDocument, async event => {
|
||||
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 0, 'should clear');
|
||||
});
|
||||
|
||||
const secondResource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async event => {
|
||||
await vscode.commands.executeCommand('notebook.cell.execute', { start: 0, end: 1 }, notebook.uri);
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor?.notebook.uri.fsPath, secondResource.fsPath);
|
||||
});
|
||||
});
|
||||
|
||||
test('cell execute command takes arguments 2', async () => {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
let firstCellExecuted = false;
|
||||
let secondCellExecuted = false;
|
||||
|
||||
const def = new DeferredPromise<void>();
|
||||
testDisposables.push(vscode.workspace.onDidChangeNotebookDocument(e => {
|
||||
e.cellChanges.forEach(change => {
|
||||
if (change.cell.index === 0 && change.executionSummary) {
|
||||
firstCellExecuted = true;
|
||||
}
|
||||
|
||||
if (change.cell.index === 1 && change.executionSummary) {
|
||||
secondCellExecuted = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (firstCellExecuted && secondCellExecuted) {
|
||||
def.complete();
|
||||
}
|
||||
}));
|
||||
|
||||
vscode.commands.executeCommand('notebook.cell.execute', { document: notebook.uri, ranges: [{ start: 0, end: 1 }, { start: 1, end: 2 }] });
|
||||
|
||||
await def.p;
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
test('document execute command takes arguments', async () => {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
const cell = editor.notebook.cellAt(0);
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||
await vscode.commands.executeCommand('notebook.execute', notebook.uri);
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
});
|
||||
});
|
||||
|
||||
test('cell execute and select kernel', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
|
||||
|
||||
const cell = editor.notebook.cellAt(0);
|
||||
|
||||
const alternativeKernel = new class extends Kernel {
|
||||
constructor() {
|
||||
super('secondaryKernel', 'Notebook Secondary Test Kernel');
|
||||
this.controller.supportsExecutionOrder = false;
|
||||
}
|
||||
|
||||
override async _runCell(cell: vscode.NotebookCell) {
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my second output', 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
};
|
||||
testDisposables.push(alternativeKernel.controller);
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||
await assertKernel(defaultKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
assert.strictEqual(cell.outputs[0].items.length, 1);
|
||||
assert.strictEqual(cell.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), cell.document.getText());
|
||||
});
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||
await assertKernel(alternativeKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
assert.strictEqual(cell.outputs[0].items.length, 1);
|
||||
assert.strictEqual(cell.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), 'my second output');
|
||||
});
|
||||
});
|
||||
|
||||
test('onDidChangeCellExecutionState is fired', async () => {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
const cell = editor.notebook.cellAt(0);
|
||||
|
||||
let eventCount = 0;
|
||||
const def = new DeferredPromise<void>();
|
||||
testDisposables.push(vscode.notebooks.onDidChangeNotebookCellExecutionState(e => {
|
||||
try {
|
||||
assert.strictEqual(e.cell.document.uri.toString(), cell.document.uri.toString(), 'event should be fired for the executing cell');
|
||||
|
||||
if (eventCount === 0) {
|
||||
assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Pending, 'should be set to Pending');
|
||||
} else if (eventCount === 1) {
|
||||
assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Executing, 'should be set to Executing');
|
||||
assert.strictEqual(cell.outputs.length, 0, 'no outputs yet: ' + JSON.stringify(cell.outputs[0]));
|
||||
} else if (e.state === vscode.NotebookCellExecutionState.Idle) {
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should have an output');
|
||||
def.complete();
|
||||
}
|
||||
|
||||
eventCount++;
|
||||
} catch (err) {
|
||||
def.error(err);
|
||||
}
|
||||
}));
|
||||
|
||||
vscode.commands.executeCommand('notebook.cell.execute', { document: notebook.uri, ranges: [{ start: 0, end: 1 }] });
|
||||
|
||||
await def.p;
|
||||
});
|
||||
|
||||
test('Output changes are applied once the promise resolves', async function () {
|
||||
|
||||
let called = false;
|
||||
|
||||
const verifyOutputSyncKernel = new class extends Kernel {
|
||||
|
||||
constructor() {
|
||||
super('verifyOutputSyncKernel', '');
|
||||
}
|
||||
|
||||
override async _execute(cells: vscode.NotebookCell[]) {
|
||||
const [cell] = cells;
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('Some output', 'text/plain')
|
||||
])]);
|
||||
assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1);
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell.notebook.cellAt(0).outputs[0].items[0].data), 'Some output');
|
||||
task.end(undefined);
|
||||
called = true;
|
||||
}
|
||||
};
|
||||
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
await assertKernel(verifyOutputSyncKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(called, true);
|
||||
verifyOutputSyncKernel.controller.dispose();
|
||||
});
|
||||
|
||||
test('executionSummary', async () => {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
const cell = editor.notebook.cellAt(0);
|
||||
|
||||
assert.strictEqual(cell.executionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.executionSummary?.executionOrder, undefined);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute');
|
||||
assert.ok(cell.executionSummary);
|
||||
assert.strictEqual(cell.executionSummary!.success, true);
|
||||
assert.strictEqual(typeof cell.executionSummary!.executionOrder, 'number');
|
||||
});
|
||||
|
||||
test('initialize executionSummary', async () => {
|
||||
|
||||
const document = await openRandomNotebookDocument();
|
||||
const cell = document.cellAt(0);
|
||||
|
||||
assert.strictEqual(cell.executionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.executionSummary?.timing?.startTime, 10);
|
||||
assert.strictEqual(cell.executionSummary?.timing?.endTime, 20);
|
||||
|
||||
});
|
||||
|
||||
test('execution cancelled when delete while executing', async () => {
|
||||
const document = await openRandomNotebookDocument();
|
||||
const cell = document.cellAt(0);
|
||||
|
||||
let executionWasCancelled = false;
|
||||
const cancelledKernel = new class extends Kernel {
|
||||
constructor() {
|
||||
super('cancelledKernel', '');
|
||||
}
|
||||
|
||||
override async _execute(cells: vscode.NotebookCell[]) {
|
||||
const [cell] = cells;
|
||||
const exe = this.controller.createNotebookCellExecution(cell);
|
||||
exe.token.onCancellationRequested(() => executionWasCancelled = true);
|
||||
}
|
||||
};
|
||||
testDisposables.push(cancelledKernel.controller);
|
||||
|
||||
await vscode.window.showNotebookDocument(document);
|
||||
await assertKernel(cancelledKernel, document);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
|
||||
// Delete executing cell
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(cell!.notebook.uri, new vscode.NotebookRange(cell!.index, cell!.index + 1), []);
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
|
||||
assert.strictEqual(executionWasCancelled, true);
|
||||
});
|
||||
|
||||
test('appendOutput to different cell', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
const cell0 = editor.notebook.cellAt(0);
|
||||
const notebookEdit = new vscode.NotebookEdit(new vscode.NotebookRange(1, 1), [new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'test 2', 'javascript')]);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(notebook.uri, [notebookEdit]);
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
const cell1 = editor.notebook.cellAt(1);
|
||||
|
||||
const nextCellKernel = new class extends Kernel {
|
||||
constructor() {
|
||||
super('nextCellKernel', 'Append to cell kernel');
|
||||
}
|
||||
|
||||
override async _runCell(cell: vscode.NotebookCell) {
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.appendOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my output')
|
||||
])], cell1);
|
||||
await task.appendOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my output 2')
|
||||
])], cell1);
|
||||
task.end(true);
|
||||
}
|
||||
};
|
||||
testDisposables.push(nextCellKernel.controller);
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||
await assertKernel(nextCellKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell0.outputs.length, 0, 'should not change cell 0');
|
||||
assert.strictEqual(cell1.outputs.length, 2, 'should update cell 1');
|
||||
assert.strictEqual(cell1.outputs[0].items.length, 1);
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell1.outputs[0].items[0].data), 'my output');
|
||||
});
|
||||
});
|
||||
|
||||
test('replaceOutput to different cell', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
const cell0 = editor.notebook.cellAt(0);
|
||||
const notebookEdit = new vscode.NotebookEdit(new vscode.NotebookRange(1, 1), [new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'test 2', 'javascript')]);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(notebook.uri, [notebookEdit]);
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
const cell1 = editor.notebook.cellAt(1);
|
||||
|
||||
const nextCellKernel = new class extends Kernel {
|
||||
constructor() {
|
||||
super('nextCellKernel', 'Replace to cell kernel');
|
||||
}
|
||||
|
||||
override async _runCell(cell: vscode.NotebookCell) {
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my output')
|
||||
])], cell1);
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my output 2')
|
||||
])], cell1);
|
||||
task.end(true);
|
||||
}
|
||||
};
|
||||
testDisposables.push(nextCellKernel.controller);
|
||||
|
||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||
await assertKernel(nextCellKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell0.outputs.length, 0, 'should not change cell 0');
|
||||
assert.strictEqual(cell1.outputs.length, 1, 'should update cell 1');
|
||||
assert.strictEqual(cell1.outputs[0].items.length, 1);
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell1.outputs[0].items[0].data), 'my output 2');
|
||||
});
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user