Merge remote-tracking branch 'origin/master' into tyriar/puppeteer
2
.github/classifier.yml
vendored
|
@ -81,7 +81,7 @@
|
||||||
hot-exit: [],
|
hot-exit: [],
|
||||||
html: [],
|
html: [],
|
||||||
install-update: [],
|
install-update: [],
|
||||||
integrated-terminal: [ Tyriar ],
|
integrated-terminal: [],
|
||||||
integration-test: [],
|
integration-test: [],
|
||||||
intellisense-config: [],
|
intellisense-config: [],
|
||||||
issue-reporter: [ RMacfarlane ],
|
issue-reporter: [ RMacfarlane ],
|
||||||
|
|
4
.gitignore
vendored
|
@ -18,9 +18,11 @@ out-vscode-min/
|
||||||
out-vscode-reh/
|
out-vscode-reh/
|
||||||
out-vscode-reh-min/
|
out-vscode-reh-min/
|
||||||
out-vscode-reh-pkg/
|
out-vscode-reh-pkg/
|
||||||
|
out-vscode-reh-web/
|
||||||
|
out-vscode-reh-web-min/
|
||||||
|
out-vscode-reh-web-pkg/
|
||||||
out-vscode-web/
|
out-vscode-web/
|
||||||
out-vscode-web-min/
|
out-vscode-web-min/
|
||||||
out-vscode-web-pkg/
|
|
||||||
src/vs/server
|
src/vs/server
|
||||||
resources/server
|
resources/server
|
||||||
build/node_modules
|
build/node_modules
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1
|
2019-07-11T05:47:05.444Z
|
||||||
|
|
|
@ -6,8 +6,8 @@ steps:
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
@ -89,9 +89,7 @@ steps:
|
||||||
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
yarn gulp vscode-reh-darwin-min-ci
|
yarn gulp vscode-reh-darwin-min-ci
|
||||||
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
yarn gulp vscode-web-darwin-min-ci
|
yarn gulp vscode-reh-web-darwin-min-ci
|
||||||
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
|
|
||||||
yarn gulp upload-vscode-sourcemaps
|
|
||||||
displayName: Build
|
displayName: Build
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
|
|
|
@ -30,7 +30,7 @@ node build/azure-pipelines/common/publish.js \
|
||||||
../vscode-server-darwin.zip
|
../vscode-server-darwin.zip
|
||||||
|
|
||||||
# publish hockeyapp symbols
|
# publish hockeyapp symbols
|
||||||
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS"
|
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" x64 "$VSCODE_HOCKEYAPP_ID_MACOS"
|
||||||
|
|
||||||
# upload configuration
|
# upload configuration
|
||||||
yarn gulp upload-vscode-configuration
|
yarn gulp upload-vscode-configuration
|
||||||
|
|
|
@ -6,8 +6,8 @@ steps:
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
|
|
@ -6,8 +6,8 @@ steps:
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
@ -34,8 +34,6 @@ steps:
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
export npm_config_arch="$(VSCODE_ARCH)"
|
|
||||||
|
|
||||||
cat << EOF > ~/.netrc
|
cat << EOF > ~/.netrc
|
||||||
machine github.com
|
machine github.com
|
||||||
login vscode
|
login vscode
|
||||||
|
@ -86,22 +84,22 @@ steps:
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
yarn gulp vscode-linux-$VSCODE_ARCH-min-ci
|
yarn gulp vscode-linux-x64-min-ci
|
||||||
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
yarn gulp vscode-reh-linux-$VSCODE_ARCH-min-ci
|
yarn gulp vscode-reh-linux-x64-min-ci
|
||||||
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
yarn gulp vscode-web-linux-$VSCODE_ARCH-min-ci
|
yarn gulp vscode-reh-web-linux-x64-min-ci
|
||||||
displayName: Build
|
displayName: Build
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
yarn gulp "electron-$(VSCODE_ARCH)"
|
yarn gulp "electron-x64"
|
||||||
|
|
||||||
# xvfb seems to be crashing often, let's make sure it's always up
|
# xvfb seems to be crashing often, let's make sure it's always up
|
||||||
service xvfb start
|
service xvfb start
|
||||||
|
|
||||||
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
|
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
|
||||||
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
|
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-x64"
|
||||||
displayName: Run unit tests
|
displayName: Run unit tests
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||||
|
|
||||||
|
@ -117,7 +115,7 @@ steps:
|
||||||
- task: PublishPipelineArtifact@0
|
- task: PublishPipelineArtifact@0
|
||||||
displayName: 'Publish Pipeline Artifact'
|
displayName: 'Publish Pipeline Artifact'
|
||||||
inputs:
|
inputs:
|
||||||
artifactName: snap-$(VSCODE_ARCH)
|
artifactName: snap-x64
|
||||||
targetPath: .build/linux/snap-tarball
|
targetPath: .build/linux/snap-tarball
|
||||||
|
|
||||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||||
|
|
|
@ -4,7 +4,7 @@ REPO="$(pwd)"
|
||||||
ROOT="$REPO/.."
|
ROOT="$REPO/.."
|
||||||
|
|
||||||
# Publish tarball
|
# Publish tarball
|
||||||
PLATFORM_LINUX="linux-$VSCODE_ARCH"
|
PLATFORM_LINUX="linux-x64"
|
||||||
BUILDNAME="VSCode-$PLATFORM_LINUX"
|
BUILDNAME="VSCode-$PLATFORM_LINUX"
|
||||||
BUILD="$ROOT/$BUILDNAME"
|
BUILD="$ROOT/$BUILDNAME"
|
||||||
BUILD_VERSION="$(date +%s)"
|
BUILD_VERSION="$(date +%s)"
|
||||||
|
@ -19,24 +19,22 @@ rm -rf $ROOT/code-*.tar.*
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
|
||||||
|
|
||||||
# Publish Remote Extension Host
|
# Publish Remote Extension Host
|
||||||
if [[ "$VSCODE_ARCH" != "ia32" ]]; then
|
LEGACY_SERVER_BUILD_NAME="vscode-reh-$PLATFORM_LINUX"
|
||||||
LEGACY_SERVER_BUILD_NAME="vscode-reh-$PLATFORM_LINUX"
|
SERVER_BUILD_NAME="vscode-server-$PLATFORM_LINUX"
|
||||||
SERVER_BUILD_NAME="vscode-server-$PLATFORM_LINUX"
|
SERVER_TARBALL_FILENAME="vscode-server-$PLATFORM_LINUX.tar.gz"
|
||||||
SERVER_TARBALL_FILENAME="vscode-server-$PLATFORM_LINUX.tar.gz"
|
SERVER_TARBALL_PATH="$ROOT/$SERVER_TARBALL_FILENAME"
|
||||||
SERVER_TARBALL_PATH="$ROOT/$SERVER_TARBALL_FILENAME"
|
|
||||||
|
|
||||||
rm -rf $ROOT/vscode-server-*.tar.*
|
rm -rf $ROOT/vscode-server-*.tar.*
|
||||||
(cd $ROOT && mv $LEGACY_SERVER_BUILD_NAME $SERVER_BUILD_NAME && tar -czf $SERVER_TARBALL_PATH $SERVER_BUILD_NAME)
|
(cd $ROOT && mv $LEGACY_SERVER_BUILD_NAME $SERVER_BUILD_NAME && tar --owner=0 --group=0 -czf $SERVER_TARBALL_PATH $SERVER_BUILD_NAME)
|
||||||
|
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "server-$PLATFORM_LINUX" archive-unsigned "$SERVER_TARBALL_FILENAME" "$VERSION" true "$SERVER_TARBALL_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "server-$PLATFORM_LINUX" archive-unsigned "$SERVER_TARBALL_FILENAME" "$VERSION" true "$SERVER_TARBALL_PATH"
|
||||||
fi
|
|
||||||
|
|
||||||
# Publish hockeyapp symbols
|
# Publish hockeyapp symbols
|
||||||
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64"
|
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "x64" "$VSCODE_HOCKEYAPP_ID_LINUX64"
|
||||||
|
|
||||||
# Publish DEB
|
# Publish DEB
|
||||||
yarn gulp "vscode-linux-$VSCODE_ARCH-build-deb"
|
yarn gulp "vscode-linux-x64-build-deb"
|
||||||
PLATFORM_DEB="linux-deb-$VSCODE_ARCH"
|
PLATFORM_DEB="linux-deb-x64"
|
||||||
DEB_ARCH="amd64"
|
DEB_ARCH="amd64"
|
||||||
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
|
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
|
||||||
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
|
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
|
||||||
|
@ -44,8 +42,8 @@ DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
|
||||||
|
|
||||||
# Publish RPM
|
# Publish RPM
|
||||||
yarn gulp "vscode-linux-$VSCODE_ARCH-build-rpm"
|
yarn gulp "vscode-linux-x64-build-rpm"
|
||||||
PLATFORM_RPM="linux-rpm-$VSCODE_ARCH"
|
PLATFORM_RPM="linux-rpm-x64"
|
||||||
RPM_ARCH="x86_64"
|
RPM_ARCH="x86_64"
|
||||||
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
|
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
|
||||||
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
|
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
|
||||||
|
@ -53,10 +51,10 @@ RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
|
||||||
|
|
||||||
# Publish Snap
|
# Publish Snap
|
||||||
yarn gulp "vscode-linux-$VSCODE_ARCH-prepare-snap"
|
yarn gulp "vscode-linux-x64-prepare-snap"
|
||||||
|
|
||||||
# Pack snap tarball artifact, in order to preserve file perms
|
# Pack snap tarball artifact, in order to preserve file perms
|
||||||
mkdir -p $REPO/.build/linux/snap-tarball
|
mkdir -p $REPO/.build/linux/snap-tarball
|
||||||
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz"
|
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz"
|
||||||
rm -rf $SNAP_TARBALL_PATH
|
rm -rf $SNAP_TARBALL_PATH
|
||||||
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
|
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
|
||||||
|
|
|
@ -16,7 +16,7 @@ steps:
|
||||||
- task: DownloadPipelineArtifact@0
|
- task: DownloadPipelineArtifact@0
|
||||||
displayName: 'Download Pipeline Artifact'
|
displayName: 'Download Pipeline Artifact'
|
||||||
inputs:
|
inputs:
|
||||||
artifactName: snap-$(VSCODE_ARCH)
|
artifactName: snap-x64
|
||||||
targetPath: .build/linux/snap-tarball
|
targetPath: .build/linux/snap-tarball
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
|
@ -31,14 +31,13 @@ steps:
|
||||||
|
|
||||||
# Define variables
|
# Define variables
|
||||||
REPO="$(pwd)"
|
REPO="$(pwd)"
|
||||||
ARCH="$(VSCODE_ARCH)"
|
SNAP_ROOT="$REPO/.build/linux/snap/x64"
|
||||||
SNAP_ROOT="$REPO/.build/linux/snap/$ARCH"
|
|
||||||
|
|
||||||
# Install build dependencies
|
# Install build dependencies
|
||||||
(cd build && yarn)
|
(cd build && yarn)
|
||||||
|
|
||||||
# Unpack snap tarball artifact, in order to preserve file perms
|
# Unpack snap tarball artifact, in order to preserve file perms
|
||||||
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$ARCH.tar.gz"
|
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz"
|
||||||
(cd .build/linux && tar -xzf $SNAP_TARBALL_PATH)
|
(cd .build/linux && tar -xzf $SNAP_TARBALL_PATH)
|
||||||
|
|
||||||
# Create snap package
|
# Create snap package
|
||||||
|
@ -52,4 +51,4 @@ steps:
|
||||||
# Publish snap package
|
# Publish snap package
|
||||||
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
|
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
|
||||||
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \
|
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \
|
||||||
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-x64" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"
|
|
@ -10,15 +10,12 @@ jobs:
|
||||||
- job: Compile
|
- job: Compile
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
variables:
|
|
||||||
VSCODE_ARCH: x64
|
|
||||||
container: vscode-x64
|
container: vscode-x64
|
||||||
steps:
|
steps:
|
||||||
- template: product-compile.yml
|
- template: product-compile.yml
|
||||||
|
|
||||||
- job: Windows
|
- job: Windows
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: VS2017-Win2016
|
vmImage: VS2017-Win2016
|
||||||
variables:
|
variables:
|
||||||
|
@ -30,7 +27,6 @@ jobs:
|
||||||
|
|
||||||
- job: Windows32
|
- job: Windows32
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WIN32_32BIT'], 'true'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: VS2017-Win2016
|
vmImage: VS2017-Win2016
|
||||||
variables:
|
variables:
|
||||||
|
@ -42,11 +38,8 @@ jobs:
|
||||||
|
|
||||||
- job: Linux
|
- job: Linux
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
variables:
|
|
||||||
VSCODE_ARCH: x64
|
|
||||||
container: vscode-x64
|
container: vscode-x64
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- Compile
|
- Compile
|
||||||
|
@ -55,11 +48,8 @@ jobs:
|
||||||
|
|
||||||
- job: LinuxSnap
|
- job: LinuxSnap
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX'], 'true'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
variables:
|
|
||||||
VSCODE_ARCH: x64
|
|
||||||
container: snapcraft
|
container: snapcraft
|
||||||
dependsOn: Linux
|
dependsOn: Linux
|
||||||
steps:
|
steps:
|
||||||
|
@ -67,7 +57,6 @@ jobs:
|
||||||
|
|
||||||
- job: LinuxArmhf
|
- job: LinuxArmhf
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ARMHF'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
variables:
|
variables:
|
||||||
|
@ -79,7 +68,6 @@ jobs:
|
||||||
|
|
||||||
- job: LinuxAlpine
|
- job: LinuxAlpine
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
variables:
|
variables:
|
||||||
|
@ -89,9 +77,19 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- template: linux/product-build-linux-multiarch.yml
|
- template: linux/product-build-linux-multiarch.yml
|
||||||
|
|
||||||
|
- job: LinuxWeb
|
||||||
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_WEB'], 'true'))
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
variables:
|
||||||
|
VSCODE_ARCH: x64
|
||||||
|
dependsOn:
|
||||||
|
- Compile
|
||||||
|
steps:
|
||||||
|
- template: web/product-build-web.yml
|
||||||
|
|
||||||
- job: macOS
|
- job: macOS
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_MACOS'], 'true'))
|
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_MACOS'], 'true'))
|
||||||
timeoutInMinutes: 120
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: macOS 10.13
|
vmImage: macOS 10.13
|
||||||
dependsOn:
|
dependsOn:
|
||||||
|
|
|
@ -6,8 +6,8 @@ steps:
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
@ -31,8 +31,6 @@ steps:
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
export npm_config_arch="$(VSCODE_ARCH)"
|
|
||||||
|
|
||||||
cat << EOF > ~/.netrc
|
cat << EOF > ~/.netrc
|
||||||
machine github.com
|
machine github.com
|
||||||
login vscode
|
login vscode
|
||||||
|
@ -105,14 +103,21 @@ steps:
|
||||||
yarn gulp compile-extensions-build
|
yarn gulp compile-extensions-build
|
||||||
yarn gulp minify-vscode
|
yarn gulp minify-vscode
|
||||||
yarn gulp minify-vscode-reh
|
yarn gulp minify-vscode-reh
|
||||||
yarn gulp minify-vscode-web
|
yarn gulp minify-vscode-reh-web
|
||||||
displayName: Compile
|
displayName: Compile
|
||||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
|
||||||
|
node build/azure-pipelines/upload-sourcemaps
|
||||||
|
displayName: Upload sourcemaps
|
||||||
|
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
|
39
build/azure-pipelines/upload-sourcemaps.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const es = require('event-stream');
|
||||||
|
const azure = require('gulp-azure-storage');
|
||||||
|
const vfs = require('vinyl-fs');
|
||||||
|
const util = require('../lib/util');
|
||||||
|
const root = path.dirname(path.dirname(__dirname));
|
||||||
|
const commit = util.getVersion(root);
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
const vs = vfs.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) // client source-maps only
|
||||||
|
.pipe(es.mapSync(f => {
|
||||||
|
f.path = `${f.base}/core/${f.relative}`;
|
||||||
|
return f;
|
||||||
|
}));
|
||||||
|
|
||||||
|
const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' });
|
||||||
|
|
||||||
|
return es.merge(vs, extensionsOut)
|
||||||
|
.pipe(es.through(function (data) {
|
||||||
|
// debug
|
||||||
|
console.log('Uploading Sourcemap', data.relative);
|
||||||
|
this.emit('data', data);
|
||||||
|
}))
|
||||||
|
.pipe(azure.upload({
|
||||||
|
account: process.env.AZURE_STORAGE_ACCOUNT,
|
||||||
|
key: process.env.AZURE_STORAGE_ACCESS_KEY,
|
||||||
|
container: 'sourcemaps',
|
||||||
|
prefix: commit + '/'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
96
build/azure-pipelines/web/product-build-web.yml
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
steps:
|
||||||
|
- script: |
|
||||||
|
mkdir -p .build
|
||||||
|
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||||
|
displayName: Prepare cache flag
|
||||||
|
|
||||||
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
|
inputs:
|
||||||
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
|
vstsFeed: 'npm-vscode'
|
||||||
|
platformIndependent: true
|
||||||
|
alias: 'Compilation'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
exit 1
|
||||||
|
displayName: Check RestoreCache
|
||||||
|
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||||
|
|
||||||
|
- task: NodeTool@0
|
||||||
|
inputs:
|
||||||
|
versionSpec: "10.15.1"
|
||||||
|
|
||||||
|
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
|
||||||
|
inputs:
|
||||||
|
versionSpec: "1.10.1"
|
||||||
|
|
||||||
|
- task: AzureKeyVault@1
|
||||||
|
displayName: 'Azure Key Vault: Get Secrets'
|
||||||
|
inputs:
|
||||||
|
azureSubscription: 'vscode-builds-subscription'
|
||||||
|
KeyVaultName: vscode
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
cat << EOF > ~/.netrc
|
||||||
|
machine github.com
|
||||||
|
login vscode
|
||||||
|
password $(github-distro-mixin-password)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git config user.email "vscode@microsoft.com"
|
||||||
|
git config user.name "VSCode"
|
||||||
|
displayName: Prepare tooling
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||||
|
git fetch distro
|
||||||
|
git merge $(node -p "require('./package.json').distro")
|
||||||
|
displayName: Merge distro
|
||||||
|
|
||||||
|
# - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
|
# inputs:
|
||||||
|
# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock'
|
||||||
|
# targetfolder: '**/node_modules, !**/node_modules/**/node_modules'
|
||||||
|
# vstsFeed: 'npm-vscode'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
|
||||||
|
displayName: Install dependencies
|
||||||
|
# condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||||
|
|
||||||
|
# - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||||
|
# inputs:
|
||||||
|
# keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock'
|
||||||
|
# targetfolder: '**/node_modules, !**/node_modules/**/node_modules'
|
||||||
|
# vstsFeed: 'npm-vscode'
|
||||||
|
# condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||||
|
|
||||||
|
# - script: |
|
||||||
|
# set -e
|
||||||
|
# yarn postinstall
|
||||||
|
# displayName: Run postinstall scripts
|
||||||
|
# condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
node build/azure-pipelines/mixin
|
||||||
|
displayName: Mix in quality
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
|
yarn gulp vscode-web-min-ci
|
||||||
|
displayName: Build
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
|
||||||
|
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \
|
||||||
|
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
|
||||||
|
./build/azure-pipelines/web/publish.sh
|
||||||
|
displayName: Publish
|
15
build/azure-pipelines/web/publish.sh
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
REPO="$(pwd)"
|
||||||
|
ROOT="$REPO/.."
|
||||||
|
|
||||||
|
# Publish Web Client
|
||||||
|
WEB_BUILD_NAME="vscode-web"
|
||||||
|
WEB_TARBALL_FILENAME="vscode-web.tar.gz"
|
||||||
|
WEB_TARBALL_PATH="$ROOT/$WEB_TARBALL_FILENAME"
|
||||||
|
|
||||||
|
rm -rf $ROOT/vscode-web.tar.*
|
||||||
|
|
||||||
|
(cd $ROOT && tar --owner=0 --group=0 -czf $WEB_TARBALL_PATH $WEB_BUILD_NAME)
|
||||||
|
|
||||||
|
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "web-standalone" archive-unsigned "$WEB_TARBALL_FILENAME" "$VERSION" true "$WEB_TARBALL_PATH"
|
|
@ -6,8 +6,8 @@ steps:
|
||||||
|
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
inputs:
|
inputs:
|
||||||
keyfile: '.build/commit'
|
keyfile: 'build/.cachesalt, .build/commit'
|
||||||
targetfolder: '.build, **/out-build, **/out-vscode-min, **/out-vscode-reh-min, **/out-vscode-web-min'
|
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
|
||||||
vstsFeed: 'npm-vscode'
|
vstsFeed: 'npm-vscode'
|
||||||
platformIndependent: true
|
platformIndependent: true
|
||||||
alias: 'Compilation'
|
alias: 'Compilation'
|
||||||
|
@ -98,7 +98,7 @@ steps:
|
||||||
$env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)"
|
$env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)"
|
||||||
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" }
|
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" }
|
||||||
exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" }
|
exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" }
|
||||||
exec { yarn gulp "vscode-web-win32-$env:VSCODE_ARCH-min-ci" }
|
exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" }
|
||||||
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" }
|
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" }
|
||||||
displayName: Build
|
displayName: Build
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,11 @@ gulp.task('vscode-reh-linux-x64-min', noop);
|
||||||
gulp.task('vscode-reh-linux-armhf-min', noop);
|
gulp.task('vscode-reh-linux-armhf-min', noop);
|
||||||
gulp.task('vscode-reh-linux-alpine-min', noop);
|
gulp.task('vscode-reh-linux-alpine-min', noop);
|
||||||
|
|
||||||
gulp.task('vscode-web-win32-ia32-min', noop);
|
gulp.task('vscode-reh-web-win32-ia32-min', noop);
|
||||||
gulp.task('vscode-web-win32-x64-min', noop);
|
gulp.task('vscode-reh-web-win32-x64-min', noop);
|
||||||
gulp.task('vscode-web-darwin-min', noop);
|
gulp.task('vscode-reh-web-darwin-min', noop);
|
||||||
gulp.task('vscode-web-linux-x64-min', noop);
|
gulp.task('vscode-reh-web-linux-x64-min', noop);
|
||||||
gulp.task('vscode-web-linux-alpine-min', noop);
|
gulp.task('vscode-reh-web-linux-alpine-min', noop);
|
||||||
|
|
||||||
function getNodeVersion() {
|
function getNodeVersion() {
|
||||||
const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
|
const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
|
||||||
|
|
|
@ -63,7 +63,7 @@ const vscodeResources = [
|
||||||
'out-build/bootstrap-amd.js',
|
'out-build/bootstrap-amd.js',
|
||||||
'out-build/bootstrap-window.js',
|
'out-build/bootstrap-window.js',
|
||||||
'out-build/paths.js',
|
'out-build/paths.js',
|
||||||
'out-build/vs/**/*.{svg,png,cur,html}',
|
'out-build/vs/**/*.{svg,png,html}',
|
||||||
'!out-build/vs/code/browser/**/*.html',
|
'!out-build/vs/code/browser/**/*.html',
|
||||||
'out-build/vs/base/common/performance.js',
|
'out-build/vs/base/common/performance.js',
|
||||||
'out-build/vs/base/node/languagePacks.js',
|
'out-build/vs/base/node/languagePacks.js',
|
||||||
|
@ -86,12 +86,6 @@ const vscodeResources = [
|
||||||
'!**/test/**'
|
'!**/test/**'
|
||||||
];
|
];
|
||||||
|
|
||||||
const BUNDLED_FILE_HEADER = [
|
|
||||||
'/*!--------------------------------------------------------',
|
|
||||||
' * Copyright (C) Microsoft Corporation. All rights reserved.',
|
|
||||||
' *--------------------------------------------------------*/'
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
const optimizeVSCodeTask = task.define('optimize-vscode', task.series(
|
const optimizeVSCodeTask = task.define('optimize-vscode', task.series(
|
||||||
util.rimraf('out-vscode'),
|
util.rimraf('out-vscode'),
|
||||||
common.optimizeTask({
|
common.optimizeTask({
|
||||||
|
@ -99,7 +93,6 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series(
|
||||||
entryPoints: vscodeEntryPoints,
|
entryPoints: vscodeEntryPoints,
|
||||||
resources: vscodeResources,
|
resources: vscodeResources,
|
||||||
loaderConfig: common.loaderConfig(nodeModules),
|
loaderConfig: common.loaderConfig(nodeModules),
|
||||||
header: BUNDLED_FILE_HEADER,
|
|
||||||
out: 'out-vscode',
|
out: 'out-vscode',
|
||||||
bundleInfo: undefined
|
bundleInfo: undefined
|
||||||
})
|
})
|
||||||
|
@ -265,16 +258,14 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
|
||||||
|
|
||||||
const src = gulp.src(out + '/**', { base: '.' })
|
const src = gulp.src(out + '/**', { base: '.' })
|
||||||
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); }))
|
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); }))
|
||||||
.pipe(util.setExecutableBit(['**/*.sh']))
|
.pipe(util.setExecutableBit(['**/*.sh']));
|
||||||
.pipe(filter(['**', '!**/*.js.map']));
|
|
||||||
|
|
||||||
const root = path.resolve(path.join(__dirname, '..'));
|
|
||||||
|
|
||||||
const extensions = gulp.src('.build/extensions/**', { base: '.build', dot: true });
|
const extensions = gulp.src('.build/extensions/**', { base: '.build', dot: true });
|
||||||
const sources = es.merge(src, extensions);
|
|
||||||
|
const sources = es.merge(src, extensions)
|
||||||
|
.pipe(filter(['**', '!**/*.js.map'], { dot: true }));
|
||||||
|
|
||||||
let version = packageJson.version;
|
let version = packageJson.version;
|
||||||
// @ts-ignore JSON checking: quality is optional
|
|
||||||
const quality = product.quality;
|
const quality = product.quality;
|
||||||
|
|
||||||
if (quality && quality !== 'stable') {
|
if (quality && quality !== 'stable') {
|
||||||
|
@ -309,6 +300,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
|
||||||
|
|
||||||
const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true });
|
const telemetry = gulp.src('.build/telemetry/**', { base: '.build/telemetry', dot: true });
|
||||||
|
|
||||||
|
const root = path.resolve(path.join(__dirname, '..'));
|
||||||
const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]));
|
const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]));
|
||||||
|
|
||||||
const deps = gulp.src(dependenciesSrc, { base: '.', dot: true })
|
const deps = gulp.src(dependenciesSrc, { base: '.', dot: true })
|
||||||
|
@ -535,32 +527,6 @@ gulp.task('vscode-translations-import', function () {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sourcemaps
|
|
||||||
|
|
||||||
gulp.task('upload-vscode-sourcemaps', () => {
|
|
||||||
const vs = gulp.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) // client source-maps only
|
|
||||||
.pipe(es.mapSync(f => {
|
|
||||||
f.path = `${f.base}/core/${f.relative}`;
|
|
||||||
return f;
|
|
||||||
}));
|
|
||||||
|
|
||||||
const extensionsOut = gulp.src(['extensions/**/out/**/*.map', '!extensions/**/node_modules/**'], { base: '.' });
|
|
||||||
const extensionsDist = gulp.src(['extensions/**/dist/**/*.map', '!extensions/**/node_modules/**'], { base: '.' });
|
|
||||||
|
|
||||||
return es.merge(vs, extensionsOut, extensionsDist)
|
|
||||||
.pipe(es.through(function (data) {
|
|
||||||
// debug
|
|
||||||
console.log('Uploading Sourcemap', data.relative);
|
|
||||||
this.emit('data', data);
|
|
||||||
}))
|
|
||||||
.pipe(azure.upload({
|
|
||||||
account: process.env.AZURE_STORAGE_ACCOUNT,
|
|
||||||
key: process.env.AZURE_STORAGE_ACCESS_KEY,
|
|
||||||
container: 'sourcemaps',
|
|
||||||
prefix: commit + '/'
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// This task is only run for the MacOS build
|
// This task is only run for the MacOS build
|
||||||
const generateVSCodeConfigurationTask = task.define('generate-vscode-configuration', () => {
|
const generateVSCodeConfigurationTask = task.define('generate-vscode-configuration', () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
151
build/gulpfile.vscode.web.js
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const path = require('path');
|
||||||
|
const es = require('event-stream');
|
||||||
|
const util = require('./lib/util');
|
||||||
|
const task = require('./lib/task');
|
||||||
|
const common = require('./lib/optimize');
|
||||||
|
const product = require('../product.json');
|
||||||
|
const rename = require('gulp-rename');
|
||||||
|
const filter = require('gulp-filter');
|
||||||
|
const json = require('gulp-json-editor');
|
||||||
|
const _ = require('underscore');
|
||||||
|
const deps = require('./dependencies');
|
||||||
|
const vfs = require('vinyl-fs');
|
||||||
|
const packageJson = require('../package.json');
|
||||||
|
const { compileBuildTask } = require('./gulpfile.compile');
|
||||||
|
|
||||||
|
const REPO_ROOT = path.dirname(__dirname);
|
||||||
|
const commit = util.getVersion(REPO_ROOT);
|
||||||
|
const BUILD_ROOT = path.dirname(REPO_ROOT);
|
||||||
|
const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web');
|
||||||
|
|
||||||
|
const productionDependencies = deps.getProductionDependencies(WEB_FOLDER);
|
||||||
|
|
||||||
|
const nodeModules = Object.keys(product.dependencies || {})
|
||||||
|
.concat(_.uniq(productionDependencies.map(d => d.name)));
|
||||||
|
|
||||||
|
const vscodeWebResources = [
|
||||||
|
|
||||||
|
// Workbench
|
||||||
|
'out-build/vs/{base,platform,editor,workbench}/**/*.{svg,png,html}',
|
||||||
|
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
|
||||||
|
'out-build/vs/**/markdown.css',
|
||||||
|
|
||||||
|
// Webview
|
||||||
|
'out-build/vs/workbench/contrib/webview/browser/pre/*.js',
|
||||||
|
|
||||||
|
// Excludes
|
||||||
|
'!out-build/vs/**/{node,electron-browser,electron-main}/**',
|
||||||
|
'!out-build/vs/editor/standalone/**',
|
||||||
|
'!out-build/vs/workbench/**/*-tb.png',
|
||||||
|
'!**/test/**'
|
||||||
|
];
|
||||||
|
|
||||||
|
const buildfile = require('../src/buildfile');
|
||||||
|
|
||||||
|
const vscodeWebEntryPoints = [
|
||||||
|
buildfile.workbenchWeb,
|
||||||
|
buildfile.serviceWorker,
|
||||||
|
buildfile.keyboardMaps,
|
||||||
|
buildfile.base
|
||||||
|
];
|
||||||
|
|
||||||
|
const optimizeVSCodeWebTask = task.define('optimize-vscode-web', task.series(
|
||||||
|
util.rimraf('out-vscode-web'),
|
||||||
|
common.optimizeTask({
|
||||||
|
src: 'out-build',
|
||||||
|
entryPoints: _.flatten(vscodeWebEntryPoints),
|
||||||
|
otherSources: [],
|
||||||
|
resources: vscodeWebResources,
|
||||||
|
loaderConfig: common.loaderConfig(nodeModules),
|
||||||
|
out: 'out-vscode-web',
|
||||||
|
bundleInfo: undefined
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
|
const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series(
|
||||||
|
optimizeVSCodeWebTask,
|
||||||
|
util.rimraf('out-vscode-web-min'),
|
||||||
|
common.minifyTask('out-vscode-web', `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
|
||||||
|
));
|
||||||
|
gulp.task(minifyVSCodeWebTask);
|
||||||
|
|
||||||
|
function packageTask(sourceFolderName, destinationFolderName) {
|
||||||
|
const destination = path.join(BUILD_ROOT, destinationFolderName);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||||
|
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
||||||
|
.pipe(filter(['**', '!**/*.js.map']));
|
||||||
|
|
||||||
|
const sources = es.merge(src);
|
||||||
|
|
||||||
|
let version = packageJson.version;
|
||||||
|
const quality = product.quality;
|
||||||
|
|
||||||
|
if (quality && quality !== 'stable') {
|
||||||
|
version += '-' + quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = product.nameShort;
|
||||||
|
const packageJsonStream = gulp.src(['remote/web/package.json'], { base: 'remote/web' })
|
||||||
|
.pipe(json({ name, version }));
|
||||||
|
|
||||||
|
const date = new Date().toISOString();
|
||||||
|
|
||||||
|
const productJsonStream = gulp.src(['product.json'], { base: '.' })
|
||||||
|
.pipe(json({ commit, date }));
|
||||||
|
|
||||||
|
const license = gulp.src(['remote/LICENSE'], { base: 'remote' });
|
||||||
|
|
||||||
|
const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(REPO_ROOT, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`]));
|
||||||
|
|
||||||
|
const deps = gulp.src(dependenciesSrc, { base: 'remote/web', dot: true })
|
||||||
|
.pipe(filter(['**', '!**/package-lock.json']))
|
||||||
|
.pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore')));
|
||||||
|
|
||||||
|
const favicon = gulp.src('resources/server/favicon.ico', { base: 'resources/server' });
|
||||||
|
|
||||||
|
let all = es.merge(
|
||||||
|
packageJsonStream,
|
||||||
|
productJsonStream,
|
||||||
|
license,
|
||||||
|
sources,
|
||||||
|
deps,
|
||||||
|
favicon
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = all
|
||||||
|
.pipe(util.skipDirectories())
|
||||||
|
.pipe(util.fixWin32DirectoryPermissions());
|
||||||
|
|
||||||
|
return result.pipe(vfs.dest(destination));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const dashed = (str) => (str ? `-${str}` : ``);
|
||||||
|
|
||||||
|
['', 'min'].forEach(minified => {
|
||||||
|
const sourceFolderName = `out-vscode-web${dashed(minified)}`;
|
||||||
|
const destinationFolderName = `vscode-web`;
|
||||||
|
|
||||||
|
const vscodeWebTaskCI = task.define(`vscode-web${dashed(minified)}-ci`, task.series(
|
||||||
|
minified ? minifyVSCodeWebTask : optimizeVSCodeWebTask,
|
||||||
|
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
|
||||||
|
packageTask(sourceFolderName, destinationFolderName)
|
||||||
|
));
|
||||||
|
gulp.task(vscodeWebTaskCI);
|
||||||
|
|
||||||
|
const vscodeWebTask = task.define(`vscode-web${dashed(minified)}`, task.series(
|
||||||
|
compileBuildTask,
|
||||||
|
vscodeWebTaskCI
|
||||||
|
));
|
||||||
|
gulp.task(vscodeWebTask);
|
||||||
|
});
|
|
@ -111,12 +111,6 @@ function fromLocalWebpack(extensionPath) {
|
||||||
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
|
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
|
||||||
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
||||||
}), 'utf8');
|
}), 'utf8');
|
||||||
if (/\.js\.map$/.test(data.path)) {
|
|
||||||
if (!fs.existsSync(path.dirname(data.path))) {
|
|
||||||
fs.mkdirSync(path.dirname(data.path));
|
|
||||||
}
|
|
||||||
fs.writeFileSync(data.path, data.contents);
|
|
||||||
}
|
|
||||||
this.emit('data', data);
|
this.emit('data', data);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -195,20 +189,21 @@ function packageLocalExtensionsStream() {
|
||||||
})
|
})
|
||||||
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
||||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
|
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
|
||||||
return es.merge(gulp.src('extensions/node_modules/**', { base: '.' }), ...localExtensionDescriptions.map(extension => {
|
const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' });
|
||||||
|
const localExtensions = localExtensionDescriptions.map(extension => {
|
||||||
return fromLocal(extension.path)
|
return fromLocal(extension.path)
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
}))
|
});
|
||||||
.pipe(util2.setExecutableBit(['**/*.sh']))
|
return es.merge(nodeModules, ...localExtensions)
|
||||||
.pipe(filter(['**', '!**/*.js.map']));
|
.pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
}
|
}
|
||||||
exports.packageLocalExtensionsStream = packageLocalExtensionsStream;
|
exports.packageLocalExtensionsStream = packageLocalExtensionsStream;
|
||||||
function packageMarketplaceExtensionsStream() {
|
function packageMarketplaceExtensionsStream() {
|
||||||
return es.merge(builtInExtensions.map(extension => {
|
const extensions = builtInExtensions.map(extension => {
|
||||||
return fromMarketplace(extension.name, extension.version, extension.metadata)
|
return fromMarketplace(extension.name, extension.version, extension.metadata)
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
}))
|
});
|
||||||
.pipe(util2.setExecutableBit(['**/*.sh']))
|
return es.merge(extensions)
|
||||||
.pipe(filter(['**', '!**/*.js.map']));
|
.pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
}
|
}
|
||||||
exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream;
|
exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream;
|
||||||
|
|
|
@ -130,12 +130,6 @@ function fromLocalWebpack(extensionPath: string): Stream {
|
||||||
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
||||||
}), 'utf8');
|
}), 'utf8');
|
||||||
|
|
||||||
if (/\.js\.map$/.test(data.path)) {
|
|
||||||
if (!fs.existsSync(path.dirname(data.path))) {
|
|
||||||
fs.mkdirSync(path.dirname(data.path));
|
|
||||||
}
|
|
||||||
fs.writeFileSync(data.path, data.contents);
|
|
||||||
}
|
|
||||||
this.emit('data', data);
|
this.emit('data', data);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -237,22 +231,22 @@ export function packageLocalExtensionsStream(): NodeJS.ReadWriteStream {
|
||||||
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
||||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
|
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
|
||||||
|
|
||||||
return es.merge(
|
const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' });
|
||||||
gulp.src('extensions/node_modules/**', { base: '.' }),
|
const localExtensions = localExtensionDescriptions.map(extension => {
|
||||||
...localExtensionDescriptions.map(extension => {
|
return fromLocal(extension.path)
|
||||||
return fromLocal(extension.path)
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
});
|
||||||
})
|
|
||||||
)
|
return es.merge(nodeModules, ...localExtensions)
|
||||||
.pipe(util2.setExecutableBit(['**/*.sh']))
|
.pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
.pipe(filter(['**', '!**/*.js.map']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function packageMarketplaceExtensionsStream(): NodeJS.ReadWriteStream {
|
export function packageMarketplaceExtensionsStream(): NodeJS.ReadWriteStream {
|
||||||
return es.merge(builtInExtensions.map(extension => {
|
const extensions = builtInExtensions.map(extension => {
|
||||||
return fromMarketplace(extension.name, extension.version, extension.metadata)
|
return fromMarketplace(extension.name, extension.version, extension.metadata)
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
}))
|
});
|
||||||
.pipe(util2.setExecutableBit(['**/*.sh']))
|
|
||||||
.pipe(filter(['**', '!**/*.js.map']));
|
return es.merge(extensions)
|
||||||
|
.pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,12 +111,17 @@ function toBundleStream(src, bundledFileHeader, bundles) {
|
||||||
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest);
|
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
const DEFAULT_FILE_HEADER = [
|
||||||
|
'/*!--------------------------------------------------------',
|
||||||
|
' * Copyright (C) Microsoft Corporation. All rights reserved.',
|
||||||
|
' *--------------------------------------------------------*/'
|
||||||
|
].join('\n');
|
||||||
function optimizeTask(opts) {
|
function optimizeTask(opts) {
|
||||||
const src = opts.src;
|
const src = opts.src;
|
||||||
const entryPoints = opts.entryPoints;
|
const entryPoints = opts.entryPoints;
|
||||||
const resources = opts.resources;
|
const resources = opts.resources;
|
||||||
const loaderConfig = opts.loaderConfig;
|
const loaderConfig = opts.loaderConfig;
|
||||||
const bundledFileHeader = opts.header;
|
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
|
||||||
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
|
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
|
||||||
const out = opts.out;
|
const out = opts.out;
|
||||||
return function () {
|
return function () {
|
||||||
|
|
|
@ -154,7 +154,7 @@ export interface IOptimizeTaskOpts {
|
||||||
/**
|
/**
|
||||||
* (basically the Copyright treatment)
|
* (basically the Copyright treatment)
|
||||||
*/
|
*/
|
||||||
header: string;
|
header?: string;
|
||||||
/**
|
/**
|
||||||
* (emit bundleInfo.json file)
|
* (emit bundleInfo.json file)
|
||||||
*/
|
*/
|
||||||
|
@ -169,12 +169,18 @@ export interface IOptimizeTaskOpts {
|
||||||
languages?: Language[];
|
languages?: Language[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_FILE_HEADER = [
|
||||||
|
'/*!--------------------------------------------------------',
|
||||||
|
' * Copyright (C) Microsoft Corporation. All rights reserved.',
|
||||||
|
' *--------------------------------------------------------*/'
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
|
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
|
||||||
const src = opts.src;
|
const src = opts.src;
|
||||||
const entryPoints = opts.entryPoints;
|
const entryPoints = opts.entryPoints;
|
||||||
const resources = opts.resources;
|
const resources = opts.resources;
|
||||||
const loaderConfig = opts.loaderConfig;
|
const loaderConfig = opts.loaderConfig;
|
||||||
const bundledFileHeader = opts.header;
|
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
|
||||||
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
|
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
|
||||||
const out = opts.out;
|
const out = opts.out;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,6 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gulp-watch": "^4.3.9"
|
"gulp-watch": "5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ yarnInstall('extensions'); // node modules shared by all extensions
|
||||||
|
|
||||||
yarnInstall('remote'); // node modules used by vscode server
|
yarnInstall('remote'); // node modules used by vscode server
|
||||||
|
|
||||||
|
yarnInstall('remote/web'); // node modules used by vscode web
|
||||||
|
|
||||||
const allExtensionFolders = fs.readdirSync('extensions');
|
const allExtensionFolders = fs.readdirSync('extensions');
|
||||||
const extensions = allExtensionFolders.filter(e => {
|
const extensions = allExtensionFolders.filter(e => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
test/**
|
test/**
|
||||||
cgmanifest.json
|
cgmanifest.json
|
||||||
|
.vscode
|
|
@ -2,4 +2,5 @@ src/**
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
out/**
|
out/**
|
||||||
extension.webpack.config.js
|
extension.webpack.config.js
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
.vscode
|
|
@ -6,3 +6,4 @@ extension.webpack.config.js
|
||||||
CONTRIBUTING.md
|
CONTRIBUTING.md
|
||||||
cgmanifest.json
|
cgmanifest.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
.vscode
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"registrations": [
|
|
||||||
{
|
|
||||||
"component": {
|
|
||||||
"type": "git",
|
|
||||||
"git": {
|
|
||||||
"name": "textmate/markdown.tmbundle",
|
|
||||||
"repositoryUrl": "https://github.com/textmate/markdown.tmbundle",
|
|
||||||
"commitHash": "11cf764606cb2cde54badb5d0e5a0758a8871c4b"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"licenseDetail": [
|
|
||||||
"Copyright (c) markdown.tmbundle authors",
|
|
||||||
"",
|
|
||||||
"If not otherwise specified (see below), files in this repository fall under the following license:",
|
|
||||||
"",
|
|
||||||
"Permission to copy, use, modify, sell and distribute this",
|
|
||||||
"software is granted. This software is provided \"as is\" without",
|
|
||||||
"express or implied warranty, and with no claim as to its",
|
|
||||||
"suitability for any purpose.",
|
|
||||||
"",
|
|
||||||
"An exception is made for files in readable text which contain their own license information,",
|
|
||||||
"or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
|
|
||||||
"to the base-name name of the original file, and an extension of txt, html, or similar. For example",
|
|
||||||
"\"tidy\" is accompanied by \"tidy-license.txt\"."
|
|
||||||
],
|
|
||||||
"license": "TextMate Bundle License",
|
|
||||||
"version": "0.0.0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 1
|
|
||||||
}
|
|
|
@ -4,3 +4,4 @@ out/test/**
|
||||||
src/**
|
src/**
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
cgmanifest.json
|
cgmanifest.json
|
||||||
|
.vscode
|
|
@ -3,3 +3,4 @@ src/**
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
extension.webpack.config.js
|
extension.webpack.config.js
|
||||||
cgmanifest.json
|
cgmanifest.json
|
||||||
|
.vscode
|
|
@ -270,27 +270,6 @@ suite('window namespace tests', () => {
|
||||||
window.createTerminal({ name: 'c', virtualProcess });
|
window.createTerminal({ name: 'c', virtualProcess });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should get dimensions event when shown', (done) => {
|
|
||||||
const reg1 = window.onDidOpenTerminal(term => {
|
|
||||||
reg1.dispose();
|
|
||||||
equal(terminal, term);
|
|
||||||
term.show();
|
|
||||||
});
|
|
||||||
const virtualProcess: TerminalVirtualProcess = {
|
|
||||||
onDidWrite: new EventEmitter<string>().event,
|
|
||||||
setDimensions: dimensions => {
|
|
||||||
ok(dimensions.columns > 0);
|
|
||||||
ok(dimensions.rows > 0);
|
|
||||||
const reg2 = window.onDidCloseTerminal(() => {
|
|
||||||
reg2.dispose();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
terminal.dispose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const terminal = window.createTerminal({ name: 'foo', virtualProcess });
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should fire Terminal.onData on write', (done) => {
|
test('should fire Terminal.onData on write', (done) => {
|
||||||
const reg1 = window.onDidOpenTerminal(term => {
|
const reg1 = window.onDidOpenTerminal(term => {
|
||||||
equal(terminal, term);
|
equal(terminal, term);
|
||||||
|
@ -313,6 +292,26 @@ suite('window namespace tests', () => {
|
||||||
const terminal = window.createTerminal({ name: 'foo', virtualProcess });
|
const terminal = window.createTerminal({ name: 'foo', virtualProcess });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should fire provide dimensions on start as the terminal has been shown', (done) => {
|
||||||
|
const reg1 = window.onDidOpenTerminal(term => {
|
||||||
|
equal(terminal, term);
|
||||||
|
reg1.dispose();
|
||||||
|
});
|
||||||
|
const virtualProcess: TerminalVirtualProcess = {
|
||||||
|
onDidWrite: new EventEmitter<string>().event,
|
||||||
|
start: (dimensions) => {
|
||||||
|
ok(dimensions!.columns > 0);
|
||||||
|
ok(dimensions!.rows > 0);
|
||||||
|
const reg3 = window.onDidCloseTerminal(() => {
|
||||||
|
reg3.dispose();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
terminal.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const terminal = window.createTerminal({ name: 'foo', virtualProcess });
|
||||||
|
});
|
||||||
|
|
||||||
test('should respect dimension overrides', (done) => {
|
test('should respect dimension overrides', (done) => {
|
||||||
const reg1 = window.onDidOpenTerminal(term => {
|
const reg1 = window.onDidOpenTerminal(term => {
|
||||||
equal(terminal, term);
|
equal(terminal, term);
|
||||||
|
|
1
extensions/yaml/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
node_modules
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "code-oss-dev",
|
"name": "code-oss-dev",
|
||||||
"version": "1.37.0",
|
"version": "1.37.0",
|
||||||
"distro": "4d4ca170652edf13efd5916e009bdc9c0d4d1103",
|
"distro": "a76f8ddb784119243aa004071cea17c5a74b1e60",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,6 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"applicationinsights": "1.0.8",
|
"applicationinsights": "1.0.8",
|
||||||
"getmac": "1.4.1",
|
|
||||||
"graceful-fs": "4.1.11",
|
"graceful-fs": "4.1.11",
|
||||||
"http-proxy-agent": "^2.1.0",
|
"http-proxy-agent": "^2.1.0",
|
||||||
"https-proxy-agent": "^2.2.1",
|
"https-proxy-agent": "^2.2.1",
|
||||||
|
@ -157,4 +156,4 @@
|
||||||
"windows-mutex": "0.2.1",
|
"windows-mutex": "0.2.1",
|
||||||
"windows-process-tree": "0.2.4"
|
"windows-process-tree": "0.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
3
remote/web/.yarnrc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
disturl "http://nodejs.org/dist"
|
||||||
|
target "10.11.0"
|
||||||
|
runtime "node"
|
11
remote/web/package.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "vscode-web",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"onigasm-umd": "^2.2.2",
|
||||||
|
"vscode-textmate": "^4.1.1",
|
||||||
|
"xterm": "3.15.0-beta67",
|
||||||
|
"xterm-addon-search": "0.2.0-beta2",
|
||||||
|
"xterm-addon-web-links": "0.1.0-beta10"
|
||||||
|
}
|
||||||
|
}
|
42
remote/web/yarn.lock
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
nan@^2.14.0:
|
||||||
|
version "2.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||||
|
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||||
|
|
||||||
|
onigasm-umd@^2.2.2:
|
||||||
|
version "2.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.2.tgz#b989d762df61f899a3052ac794a50bd93fe20257"
|
||||||
|
integrity sha512-v2eMOJu7iE444L2iJN+U6s6s5S0y7oj/N0DAkrd6wokRtTVoq/v/yaDI1lIqFrTeJbNtqNzYvguDF5yNzW3Rvw==
|
||||||
|
|
||||||
|
oniguruma@^7.2.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/oniguruma/-/oniguruma-7.2.0.tgz#c9a59c1ea7b9fe67e237a02e02139b638856f3af"
|
||||||
|
integrity sha512-bh+ZLdykY1sdIx8jBp2zpLbVFDBc3XmKH4Ceo2lijNaN1WhEqtnpqFlmtCbRuDB17nJ58RAUStVwfW8e8uEbnA==
|
||||||
|
dependencies:
|
||||||
|
nan "^2.14.0"
|
||||||
|
|
||||||
|
vscode-textmate@^4.1.1:
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c"
|
||||||
|
integrity sha512-1U4ih0E/KP1zNK/EbpUqyYtI7PY+Ccd2nDGTtiMR/UalLFnmaYkwoWhN1oI7B91ptBN8NdVwWuvyUnvJAulCUw==
|
||||||
|
dependencies:
|
||||||
|
oniguruma "^7.2.0"
|
||||||
|
|
||||||
|
xterm-addon-search@0.2.0-beta2:
|
||||||
|
version "0.2.0-beta2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.2.0-beta2.tgz#c3173f0a6f207ee9f1848849174ee5d6b6ce8262"
|
||||||
|
integrity sha512-XEcwi2TeFGk2MuIFjiI/OpVXSNO5dGQBvHH3o+9KzqG3ooVqhhDqzwxs092QGNcNCGh8hGn/PWZiczaBBnKm/g==
|
||||||
|
|
||||||
|
xterm-addon-web-links@0.1.0-beta10:
|
||||||
|
version "0.1.0-beta10"
|
||||||
|
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23"
|
||||||
|
integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg==
|
||||||
|
|
||||||
|
xterm@3.15.0-beta67:
|
||||||
|
version "3.15.0-beta67"
|
||||||
|
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta67.tgz#71973e174bdc08df620945eecd3f87912f1ac550"
|
||||||
|
integrity sha512-qLfo9GHVlu/IxgDI3vRGObWZM7UL4eLhMfjZhprx2aXNMpzmrOW6l3JDRsCjUWm93EoVavbULtnDhGSiTlKitQ==
|
|
@ -15,7 +15,7 @@ import { ButtonGroup, IButtonStyles } from 'vs/base/browser/ui/button/button';
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||||
import { isMacintosh } from 'vs/base/common/platform';
|
import { isMacintosh, isLinux } from 'vs/base/common/platform';
|
||||||
|
|
||||||
export interface IDialogOptions {
|
export interface IDialogOptions {
|
||||||
cancelId?: number;
|
cancelId?: number;
|
||||||
|
@ -97,9 +97,9 @@ export class Dialog extends Disposable {
|
||||||
clearNode(this.buttonsContainer);
|
clearNode(this.buttonsContainer);
|
||||||
|
|
||||||
let focusedButton = 0;
|
let focusedButton = 0;
|
||||||
this.buttonGroup = new ButtonGroup(this.buttonsContainer, this.buttons.length, { title: true });
|
const buttonGroup = this.buttonGroup = new ButtonGroup(this.buttonsContainer, this.buttons.length, { title: true });
|
||||||
const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId);
|
const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId);
|
||||||
this.buttonGroup.buttons.forEach((button, index) => {
|
buttonGroup.buttons.forEach((button, index) => {
|
||||||
button.label = mnemonicButtonLabel(buttonMap[index].label, true);
|
button.label = mnemonicButtonLabel(buttonMap[index].label, true);
|
||||||
|
|
||||||
this._register(button.onDidClick(e => {
|
this._register(button.onDidClick(e => {
|
||||||
|
@ -115,18 +115,16 @@ export class Dialog extends Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventHandled = false;
|
let eventHandled = false;
|
||||||
if (this.buttonGroup) {
|
if (evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) {
|
||||||
if (evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) {
|
focusedButton = focusedButton + buttonGroup.buttons.length - 1;
|
||||||
focusedButton = focusedButton + this.buttonGroup.buttons.length - 1;
|
focusedButton = focusedButton % buttonGroup.buttons.length;
|
||||||
focusedButton = focusedButton % this.buttonGroup.buttons.length;
|
buttonGroup.buttons[focusedButton].focus();
|
||||||
this.buttonGroup.buttons[focusedButton].focus();
|
eventHandled = true;
|
||||||
eventHandled = true;
|
} else if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
|
||||||
} else if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
|
focusedButton++;
|
||||||
focusedButton++;
|
focusedButton = focusedButton % buttonGroup.buttons.length;
|
||||||
focusedButton = focusedButton % this.buttonGroup.buttons.length;
|
buttonGroup.buttons[focusedButton].focus();
|
||||||
this.buttonGroup.buttons[focusedButton].focus();
|
eventHandled = true;
|
||||||
eventHandled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventHandled) {
|
if (eventHandled) {
|
||||||
|
@ -192,7 +190,11 @@ export class Dialog extends Disposable {
|
||||||
show(this.element);
|
show(this.element);
|
||||||
|
|
||||||
// Focus first element
|
// Focus first element
|
||||||
this.buttonGroup.buttons[focusedButton].focus();
|
buttonMap.forEach((value, index) => {
|
||||||
|
if (value.index === focusedButton) {
|
||||||
|
buttonGroup.buttons[index].focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +245,8 @@ export class Dialog extends Disposable {
|
||||||
buttonMap.push({ label: button, index: index });
|
buttonMap.push({ label: button, index: index });
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMacintosh) {
|
// macOS/linux: reverse button order
|
||||||
|
if (isMacintosh || isLinux) {
|
||||||
if (cancelId !== undefined) {
|
if (cancelId !== undefined) {
|
||||||
const cancelButton = buttonMap.splice(cancelId, 1)[0];
|
const cancelButton = buttonMap.splice(cancelId, 1)[0];
|
||||||
buttonMap.reverse();
|
buttonMap.reverse();
|
||||||
|
|
|
@ -329,6 +329,7 @@ export function mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
|
||||||
|
|
||||||
return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
||||||
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
||||||
|
|| (event.keyCode >= KeyCode.NUMPAD_0 && event.keyCode <= KeyCode.NUMPAD_9)
|
||||||
|| (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE);
|
|| (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,13 @@ export class Sash extends Disposable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const iframes = getElementsByTagName('iframe');
|
// Select both iframes and webviews; internally Electron nests an iframe
|
||||||
|
// in its <webview> component, but this isn't queryable.
|
||||||
|
const iframes = [
|
||||||
|
...getElementsByTagName('iframe'),
|
||||||
|
...getElementsByTagName('webview'),
|
||||||
|
];
|
||||||
|
|
||||||
for (const iframe of iframes) {
|
for (const iframe of iframes) {
|
||||||
iframe.style.pointerEvents = 'none'; // disable mouse events on iframes as long as we drag the sash
|
iframe.style.pointerEvents = 'none'; // disable mouse events on iframes as long as we drag the sash
|
||||||
}
|
}
|
||||||
|
@ -280,7 +286,6 @@ export class Sash extends Disposable {
|
||||||
|
|
||||||
dispose(disposables);
|
dispose(disposables);
|
||||||
|
|
||||||
const iframes = getElementsByTagName('iframe');
|
|
||||||
for (const iframe of iframes) {
|
for (const iframe of iframes) {
|
||||||
iframe.style.pointerEvents = 'auto';
|
iframe.style.pointerEvents = 'auto';
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monaco-split-view2 > .split-view-container > .split-view-view:not(.visible) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.monaco-split-view2.vertical > .split-view-container > .split-view-view {
|
.monaco-split-view2.vertical > .split-view-container > .split-view-view {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,9 @@ export interface IView {
|
||||||
readonly maximumSize: number;
|
readonly maximumSize: number;
|
||||||
readonly onDidChange: Event<number | undefined>;
|
readonly onDidChange: Event<number | undefined>;
|
||||||
readonly priority?: LayoutPriority;
|
readonly priority?: LayoutPriority;
|
||||||
|
readonly snap?: boolean;
|
||||||
layout(size: number, orientation: Orientation): void;
|
layout(size: number, orientation: Orientation): void;
|
||||||
|
setVisible?(visible: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISashEvent {
|
interface ISashEvent {
|
||||||
|
@ -57,12 +59,79 @@ interface ISashEvent {
|
||||||
alt: boolean;
|
alt: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IViewItem {
|
abstract class ViewItem {
|
||||||
view: IView;
|
|
||||||
size: number;
|
set size(size: number) {
|
||||||
container: HTMLElement;
|
this._size = size;
|
||||||
disposable: IDisposable;
|
}
|
||||||
layout(): void;
|
|
||||||
|
get size(): number {
|
||||||
|
return this._size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private cachedSize: number | undefined = undefined;
|
||||||
|
|
||||||
|
get visible(): boolean {
|
||||||
|
return typeof this.cachedSize === 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
set visible(visible: boolean) {
|
||||||
|
if (visible === this.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
this.size = this.cachedSize!;
|
||||||
|
this.cachedSize = undefined;
|
||||||
|
} else {
|
||||||
|
this.cachedSize = this.size;
|
||||||
|
this.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.toggleClass(this.container, 'visible', visible);
|
||||||
|
|
||||||
|
if (this.view.setVisible) {
|
||||||
|
this.view.setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get minimumSize(): number { return this.visible ? this.view.minimumSize : 0; }
|
||||||
|
get viewMinimumSize(): number { return this.view.minimumSize; }
|
||||||
|
get maximumSize(): number { return this.visible ? this.view.maximumSize : 0; }
|
||||||
|
get viewMaximumSize(): number { return this.view.maximumSize; }
|
||||||
|
get priority(): LayoutPriority | undefined { return this.view.priority; }
|
||||||
|
get snap(): boolean { return !!this.view.snap; }
|
||||||
|
|
||||||
|
constructor(protected container: HTMLElement, private view: IView, private _size: number, private disposable: IDisposable) {
|
||||||
|
dom.addClass(container, 'visible');
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract layout(): void;
|
||||||
|
|
||||||
|
layoutView(orientation: Orientation): void {
|
||||||
|
this.view.layout(this.size, orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): IView {
|
||||||
|
this.disposable.dispose();
|
||||||
|
return this.view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VerticalViewItem extends ViewItem {
|
||||||
|
|
||||||
|
layout(): void {
|
||||||
|
this.container.style.height = `${this.size}px`;
|
||||||
|
this.layoutView(Orientation.VERTICAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HorizontalViewItem extends ViewItem {
|
||||||
|
|
||||||
|
layout(): void {
|
||||||
|
this.container.style.width = `${this.size}px`;
|
||||||
|
this.layoutView(Orientation.HORIZONTAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISashItem {
|
interface ISashItem {
|
||||||
|
@ -78,6 +147,8 @@ interface ISashDragState {
|
||||||
minDelta: number;
|
minDelta: number;
|
||||||
maxDelta: number;
|
maxDelta: number;
|
||||||
alt: boolean;
|
alt: boolean;
|
||||||
|
snapIndex: number | undefined;
|
||||||
|
snapLimitDelta: number | undefined;
|
||||||
disposable: IDisposable;
|
disposable: IDisposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +175,7 @@ export class SplitView extends Disposable {
|
||||||
private size = 0;
|
private size = 0;
|
||||||
private contentSize = 0;
|
private contentSize = 0;
|
||||||
private proportions: undefined | number[] = undefined;
|
private proportions: undefined | number[] = undefined;
|
||||||
private viewItems: IViewItem[] = [];
|
private viewItems: ViewItem[] = [];
|
||||||
private sashItems: ISashItem[] = [];
|
private sashItems: ISashItem[] = [];
|
||||||
private sashDragState: ISashDragState;
|
private sashDragState: ISashDragState;
|
||||||
private state: State = State.Idle;
|
private state: State = State.Idle;
|
||||||
|
@ -122,11 +193,11 @@ export class SplitView extends Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
get minimumSize(): number {
|
get minimumSize(): number {
|
||||||
return this.viewItems.reduce((r, item) => r + item.view.minimumSize, 0);
|
return this.viewItems.reduce((r, item) => r + item.minimumSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
get maximumSize(): number {
|
get maximumSize(): number {
|
||||||
return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.view.maximumSize, 0);
|
return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.maximumSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _orthogonalStartSash: Sash | undefined;
|
private _orthogonalStartSash: Sash | undefined;
|
||||||
|
@ -201,15 +272,6 @@ export class SplitView extends Disposable {
|
||||||
const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container));
|
const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container));
|
||||||
const disposable = combinedDisposable(onChangeDisposable, containerDisposable);
|
const disposable = combinedDisposable(onChangeDisposable, containerDisposable);
|
||||||
|
|
||||||
const layoutContainer = this.orientation === Orientation.VERTICAL
|
|
||||||
? () => item.container.style.height = `${item.size}px`
|
|
||||||
: () => item.container.style.width = `${item.size}px`;
|
|
||||||
|
|
||||||
const layout = () => {
|
|
||||||
layoutContainer();
|
|
||||||
item.view.layout(item.size, this.orientation);
|
|
||||||
};
|
|
||||||
|
|
||||||
let viewSize: number;
|
let viewSize: number;
|
||||||
|
|
||||||
if (typeof size === 'number') {
|
if (typeof size === 'number') {
|
||||||
|
@ -220,7 +282,10 @@ export class SplitView extends Disposable {
|
||||||
viewSize = view.minimumSize;
|
viewSize = view.minimumSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
const item: IViewItem = { view, container, size: viewSize, layout, disposable };
|
const item = this.orientation === Orientation.VERTICAL
|
||||||
|
? new VerticalViewItem(container, view, viewSize, disposable)
|
||||||
|
: new HorizontalViewItem(container, view, viewSize, disposable);
|
||||||
|
|
||||||
this.viewItems.splice(index, 0, item);
|
this.viewItems.splice(index, 0, item);
|
||||||
|
|
||||||
// Add sash
|
// Add sash
|
||||||
|
@ -280,7 +345,7 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
// Remove view
|
// Remove view
|
||||||
const viewItem = this.viewItems.splice(index, 1)[0];
|
const viewItem = this.viewItems.splice(index, 1)[0];
|
||||||
viewItem.disposable.dispose();
|
const view = viewItem.dispose();
|
||||||
|
|
||||||
// Remove sash
|
// Remove sash
|
||||||
if (this.viewItems.length >= 1) {
|
if (this.viewItems.length >= 1) {
|
||||||
|
@ -296,7 +361,7 @@ export class SplitView extends Disposable {
|
||||||
this.distributeViewSizes();
|
this.distributeViewSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
return viewItem.view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveView(from: number, to: number): void {
|
moveView(from: number, to: number): void {
|
||||||
|
@ -327,6 +392,27 @@ export class SplitView extends Disposable {
|
||||||
this.addView(fromView, toSize, to);
|
this.addView(fromView, toSize, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isViewVisible(index: number): boolean {
|
||||||
|
if (index < 0 || index >= this.viewItems.length) {
|
||||||
|
throw new Error('Index out of bounds');
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewItem = this.viewItems[index];
|
||||||
|
return viewItem.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
setViewVisible(index: number, visible: boolean): void {
|
||||||
|
if (index < 0 || index >= this.viewItems.length) {
|
||||||
|
throw new Error('Index out of bounds');
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewItem = this.viewItems[index];
|
||||||
|
viewItem.visible = visible;
|
||||||
|
|
||||||
|
this.distributeEmptySpace(index);
|
||||||
|
this.layoutViews();
|
||||||
|
}
|
||||||
|
|
||||||
private relayout(lowPriorityIndex?: number, highPriorityIndex?: number): void {
|
private relayout(lowPriorityIndex?: number, highPriorityIndex?: number): void {
|
||||||
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
|
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
|
||||||
const lowPriorityIndexes = typeof lowPriorityIndex === 'number' ? [lowPriorityIndex] : undefined;
|
const lowPriorityIndexes = typeof lowPriorityIndex === 'number' ? [lowPriorityIndex] : undefined;
|
||||||
|
@ -344,14 +430,14 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
if (!this.proportions) {
|
if (!this.proportions) {
|
||||||
const indexes = range(this.viewItems.length);
|
const indexes = range(this.viewItems.length);
|
||||||
const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.Low);
|
const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low);
|
||||||
const highPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.High);
|
const highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High);
|
||||||
|
|
||||||
this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
|
this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.viewItems.length; i++) {
|
for (let i = 0; i < this.viewItems.length; i++) {
|
||||||
const item = this.viewItems[i];
|
const item = this.viewItems[i];
|
||||||
item.size = clamp(Math.round(this.proportions[i] * size), item.view.minimumSize, item.view.maximumSize);
|
item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,35 +477,72 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
if (isLastSash) {
|
if (isLastSash) {
|
||||||
const viewItem = this.viewItems[index];
|
const viewItem = this.viewItems[index];
|
||||||
minDelta = (viewItem.view.minimumSize - viewItem.size) / 2;
|
minDelta = (viewItem.minimumSize - viewItem.size) / 2;
|
||||||
maxDelta = (viewItem.view.maximumSize - viewItem.size) / 2;
|
maxDelta = (viewItem.maximumSize - viewItem.size) / 2;
|
||||||
} else {
|
} else {
|
||||||
const viewItem = this.viewItems[index + 1];
|
const viewItem = this.viewItems[index + 1];
|
||||||
minDelta = (viewItem.size - viewItem.view.maximumSize) / 2;
|
minDelta = (viewItem.size - viewItem.maximumSize) / 2;
|
||||||
maxDelta = (viewItem.size - viewItem.view.minimumSize) / 2;
|
maxDelta = (viewItem.size - viewItem.minimumSize) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, disposable };
|
let snapIndex: number | undefined;
|
||||||
|
let snapLimitDelta: number | undefined;
|
||||||
|
|
||||||
|
if (!alt) {
|
||||||
|
const upIndexes = range(index, -1);
|
||||||
|
const downIndexes = range(index + 1, this.viewItems.length);
|
||||||
|
const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);
|
||||||
|
const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - sizes[i]), 0);
|
||||||
|
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);
|
||||||
|
const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].maximumSize), 0);
|
||||||
|
const minDelta = Math.max(minDeltaUp, minDeltaDown);
|
||||||
|
const maxDelta = Math.min(maxDeltaDown, maxDeltaUp);
|
||||||
|
|
||||||
|
const snapBefore = this.viewItems[index].snap;
|
||||||
|
const snapAfter = this.viewItems[index + 1].snap;
|
||||||
|
|
||||||
|
if (snapBefore && snapAfter) {
|
||||||
|
snapIndex = index + 1 < (this.viewItems.length - index - 1) ? index : index + 1;
|
||||||
|
} else if (snapBefore) {
|
||||||
|
snapIndex = index;
|
||||||
|
} else if (snapAfter) {
|
||||||
|
snapIndex = index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof snapIndex === 'number') {
|
||||||
|
if (this.viewItems[snapIndex].visible) {
|
||||||
|
snapLimitDelta = snapIndex === index
|
||||||
|
? minDelta - (this.viewItems[index].viewMinimumSize / 2)
|
||||||
|
: maxDelta + (this.viewItems[index + 1].viewMinimumSize / 2);
|
||||||
|
} else {
|
||||||
|
snapLimitDelta = snapIndex === index
|
||||||
|
? minDelta + (this.viewItems[index].viewMinimumSize / 2)
|
||||||
|
: maxDelta - (this.viewItems[index + 1].viewMinimumSize / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, snapIndex, snapLimitDelta, disposable };
|
||||||
};
|
};
|
||||||
|
|
||||||
resetSashDragState(start, alt);
|
resetSashDragState(start, alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSashChange({ current }: ISashEvent): void {
|
private onSashChange({ current }: ISashEvent): void {
|
||||||
const { index, start, sizes, alt, minDelta, maxDelta } = this.sashDragState;
|
const { index, start, sizes, alt, minDelta, maxDelta, snapIndex, snapLimitDelta } = this.sashDragState;
|
||||||
this.sashDragState.current = current;
|
this.sashDragState.current = current;
|
||||||
|
|
||||||
const delta = current - start;
|
const delta = current - start;
|
||||||
const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta);
|
const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapIndex, snapLimitDelta);
|
||||||
|
|
||||||
if (alt) {
|
if (alt) {
|
||||||
const isLastSash = index === this.sashItems.length - 1;
|
const isLastSash = index === this.sashItems.length - 1;
|
||||||
const newSizes = this.viewItems.map(i => i.size);
|
const newSizes = this.viewItems.map(i => i.size);
|
||||||
const viewItemIndex = isLastSash ? index : index + 1;
|
const viewItemIndex = isLastSash ? index : index + 1;
|
||||||
const viewItem = this.viewItems[viewItemIndex];
|
const viewItem = this.viewItems[viewItemIndex];
|
||||||
const newMinDelta = viewItem.size - viewItem.view.maximumSize;
|
const newMinDelta = viewItem.size - viewItem.maximumSize;
|
||||||
const newMaxDelta = viewItem.size - viewItem.view.minimumSize;
|
const newMaxDelta = viewItem.size - viewItem.minimumSize;
|
||||||
const resizeIndex = isLastSash ? index - 1 : index + 1;
|
const resizeIndex = isLastSash ? index - 1 : index + 1;
|
||||||
|
|
||||||
this.resize(resizeIndex, -newDelta, newSizes, undefined, undefined, newMinDelta, newMaxDelta);
|
this.resize(resizeIndex, -newDelta, newSizes, undefined, undefined, newMinDelta, newMaxDelta);
|
||||||
|
@ -435,7 +558,7 @@ export class SplitView extends Disposable {
|
||||||
this.saveProportions();
|
this.saveProportions();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onViewChange(item: IViewItem, size: number | undefined): void {
|
private onViewChange(item: ViewItem, size: number | undefined): void {
|
||||||
const index = this.viewItems.indexOf(item);
|
const index = this.viewItems.indexOf(item);
|
||||||
|
|
||||||
if (index < 0 || index >= this.viewItems.length) {
|
if (index < 0 || index >= this.viewItems.length) {
|
||||||
|
@ -443,7 +566,7 @@ export class SplitView extends Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
size = typeof size === 'number' ? size : item.size;
|
size = typeof size === 'number' ? size : item.size;
|
||||||
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
|
size = clamp(size, item.minimumSize, item.maximumSize);
|
||||||
|
|
||||||
if (this.inverseAltBehavior && index > 0) {
|
if (this.inverseAltBehavior && index > 0) {
|
||||||
// In this case, we want the view to grow or shrink both sides equally
|
// In this case, we want the view to grow or shrink both sides equally
|
||||||
|
@ -470,13 +593,13 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
const item = this.viewItems[index];
|
const item = this.viewItems[index];
|
||||||
size = Math.round(size);
|
size = Math.round(size);
|
||||||
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
|
size = clamp(size, item.minimumSize, item.maximumSize);
|
||||||
let delta = size - item.size;
|
let delta = size - item.size;
|
||||||
|
|
||||||
if (delta !== 0 && index < this.viewItems.length - 1) {
|
if (delta !== 0 && index < this.viewItems.length - 1) {
|
||||||
const downIndexes = range(index + 1, this.viewItems.length);
|
const downIndexes = range(index + 1, this.viewItems.length);
|
||||||
const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
|
const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].minimumSize), 0);
|
||||||
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
|
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - this.viewItems[i].size), 0);
|
||||||
const deltaDown = clamp(delta, -expandDown, collapseDown);
|
const deltaDown = clamp(delta, -expandDown, collapseDown);
|
||||||
|
|
||||||
this.resize(index, deltaDown);
|
this.resize(index, deltaDown);
|
||||||
|
@ -485,8 +608,8 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
if (delta !== 0 && index > 0) {
|
if (delta !== 0 && index > 0) {
|
||||||
const upIndexes = range(index - 1, -1);
|
const upIndexes = range(index - 1, -1);
|
||||||
const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
|
const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].minimumSize), 0);
|
||||||
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
|
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - this.viewItems[i].size), 0);
|
||||||
const deltaUp = clamp(-delta, -collapseUp, expandUp);
|
const deltaUp = clamp(-delta, -collapseUp, expandUp);
|
||||||
|
|
||||||
this.resize(index - 1, deltaUp);
|
this.resize(index - 1, deltaUp);
|
||||||
|
@ -521,7 +644,9 @@ export class SplitView extends Disposable {
|
||||||
lowPriorityIndexes?: number[],
|
lowPriorityIndexes?: number[],
|
||||||
highPriorityIndexes?: number[],
|
highPriorityIndexes?: number[],
|
||||||
overloadMinDelta: number = Number.NEGATIVE_INFINITY,
|
overloadMinDelta: number = Number.NEGATIVE_INFINITY,
|
||||||
overloadMaxDelta: number = Number.POSITIVE_INFINITY
|
overloadMaxDelta: number = Number.POSITIVE_INFINITY,
|
||||||
|
snapIndex?: number,
|
||||||
|
snapLimitDelta?: number
|
||||||
): number {
|
): number {
|
||||||
if (index < 0 || index >= this.viewItems.length) {
|
if (index < 0 || index >= this.viewItems.length) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -550,18 +675,28 @@ export class SplitView extends Disposable {
|
||||||
const downItems = downIndexes.map(i => this.viewItems[i]);
|
const downItems = downIndexes.map(i => this.viewItems[i]);
|
||||||
const downSizes = downIndexes.map(i => sizes[i]);
|
const downSizes = downIndexes.map(i => sizes[i]);
|
||||||
|
|
||||||
const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.minimumSize - sizes[i]), 0);
|
const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);
|
||||||
const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
|
const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - sizes[i]), 0);
|
||||||
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
|
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);
|
||||||
const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.maximumSize), 0);
|
const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].maximumSize), 0);
|
||||||
const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);
|
const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);
|
||||||
const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);
|
const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);
|
||||||
|
|
||||||
|
if (typeof snapIndex === 'number' && typeof snapLimitDelta === 'number') {
|
||||||
|
const snapView = this.viewItems[snapIndex];
|
||||||
|
|
||||||
|
snapView.visible = snapIndex === index
|
||||||
|
? delta >= snapLimitDelta // up
|
||||||
|
: delta < snapLimitDelta; // down
|
||||||
|
|
||||||
|
return this.resize(index, delta, sizes, lowPriorityIndexes, highPriorityIndexes, overloadMinDelta, overloadMaxDelta);
|
||||||
|
}
|
||||||
|
|
||||||
delta = clamp(delta, minDelta, maxDelta);
|
delta = clamp(delta, minDelta, maxDelta);
|
||||||
|
|
||||||
for (let i = 0, deltaUp = delta; i < upItems.length; i++) {
|
for (let i = 0, deltaUp = delta; i < upItems.length; i++) {
|
||||||
const item = upItems[i];
|
const item = upItems[i];
|
||||||
const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize);
|
const size = clamp(upSizes[i] + deltaUp, item.minimumSize, item.maximumSize);
|
||||||
const viewDelta = size - upSizes[i];
|
const viewDelta = size - upSizes[i];
|
||||||
|
|
||||||
deltaUp -= viewDelta;
|
deltaUp -= viewDelta;
|
||||||
|
@ -570,7 +705,7 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
for (let i = 0, deltaDown = delta; i < downItems.length; i++) {
|
for (let i = 0, deltaDown = delta; i < downItems.length; i++) {
|
||||||
const item = downItems[i];
|
const item = downItems[i];
|
||||||
const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize);
|
const size = clamp(downSizes[i] - deltaDown, item.minimumSize, item.maximumSize);
|
||||||
const viewDelta = size - downSizes[i];
|
const viewDelta = size - downSizes[i];
|
||||||
|
|
||||||
deltaDown += viewDelta;
|
deltaDown += viewDelta;
|
||||||
|
@ -580,13 +715,19 @@ export class SplitView extends Disposable {
|
||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
private distributeEmptySpace(): void {
|
private distributeEmptySpace(lowPriorityIndex?: number): void {
|
||||||
let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
|
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
|
||||||
let emptyDelta = this.size - contentSize;
|
let emptyDelta = this.size - contentSize;
|
||||||
|
|
||||||
for (let i = this.viewItems.length - 1; emptyDelta !== 0 && i >= 0; i--) {
|
const indexes = range(this.viewItems.length - 1, -1);
|
||||||
const item = this.viewItems[i];
|
|
||||||
const size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize);
|
if (typeof lowPriorityIndex === 'number') {
|
||||||
|
pushToEnd(indexes, lowPriorityIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; emptyDelta !== 0 && i < indexes.length; i++) {
|
||||||
|
const item = this.viewItems[indexes[i]];
|
||||||
|
const size = clamp(item.size + emptyDelta, item.minimumSize, item.maximumSize);
|
||||||
const viewDelta = size - item.size;
|
const viewDelta = size - item.size;
|
||||||
|
|
||||||
emptyDelta -= viewDelta;
|
emptyDelta -= viewDelta;
|
||||||
|
@ -606,30 +747,43 @@ export class SplitView extends Disposable {
|
||||||
|
|
||||||
// Update sashes enablement
|
// Update sashes enablement
|
||||||
let previous = false;
|
let previous = false;
|
||||||
const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous);
|
const collapsesDown = this.viewItems.map(i => previous = (i.size - i.minimumSize > 0) || previous);
|
||||||
|
|
||||||
previous = false;
|
previous = false;
|
||||||
const expandsDown = this.viewItems.map(i => previous = (i.view.maximumSize - i.size > 0) || previous);
|
const expandsDown = this.viewItems.map(i => previous = (i.maximumSize - i.size > 0) || previous);
|
||||||
|
|
||||||
const reverseViews = [...this.viewItems].reverse();
|
const reverseViews = [...this.viewItems].reverse();
|
||||||
previous = false;
|
previous = false;
|
||||||
const collapsesUp = reverseViews.map(i => previous = (i.size - i.view.minimumSize > 0) || previous).reverse();
|
const collapsesUp = reverseViews.map(i => previous = (i.size - i.minimumSize > 0) || previous).reverse();
|
||||||
|
|
||||||
previous = false;
|
previous = false;
|
||||||
const expandsUp = reverseViews.map(i => previous = (i.view.maximumSize - i.size > 0) || previous).reverse();
|
const expandsUp = reverseViews.map(i => previous = (i.maximumSize - i.size > 0) || previous).reverse();
|
||||||
|
|
||||||
this.sashItems.forEach((s, i) => {
|
this.sashItems.forEach((s, i) => {
|
||||||
const min = !(collapsesDown[i] && expandsUp[i + 1]);
|
if (!this.viewItems[i].visible) {
|
||||||
const max = !(expandsDown[i] && collapsesUp[i + 1]);
|
|
||||||
|
|
||||||
if (min && max) {
|
|
||||||
s.sash.state = SashState.Disabled;
|
s.sash.state = SashState.Disabled;
|
||||||
} else if (min && !max) {
|
|
||||||
s.sash.state = SashState.Minimum;
|
|
||||||
} else if (!min && max) {
|
|
||||||
s.sash.state = SashState.Maximum;
|
|
||||||
} else {
|
} else {
|
||||||
s.sash.state = SashState.Enabled;
|
const min = !(collapsesDown[i] && expandsUp[i + 1]);
|
||||||
|
const max = !(expandsDown[i] && collapsesUp[i + 1]);
|
||||||
|
|
||||||
|
if (min && max) {
|
||||||
|
const before = !range(0, i + 1).some(i => !this.viewItems[i].snap || this.viewItems[i].visible);
|
||||||
|
const after = !range(i + 1, this.viewItems.length).some(i => !this.viewItems[i].snap || this.viewItems[i].visible);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
s.sash.state = SashState.Minimum;
|
||||||
|
} else if (after) {
|
||||||
|
s.sash.state = SashState.Maximum;
|
||||||
|
} else {
|
||||||
|
s.sash.state = SashState.Disabled;
|
||||||
|
}
|
||||||
|
} else if (min && !max) {
|
||||||
|
s.sash.state = SashState.Minimum;
|
||||||
|
} else if (!min && max) {
|
||||||
|
s.sash.state = SashState.Maximum;
|
||||||
|
} else {
|
||||||
|
s.sash.state = SashState.Enabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -651,7 +805,7 @@ export class SplitView extends Disposable {
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
this.viewItems.forEach(i => i.disposable.dispose());
|
this.viewItems.forEach(i => i.dispose());
|
||||||
this.viewItems = [];
|
this.viewItems = [];
|
||||||
|
|
||||||
this.sashItems.forEach(i => i.disposable.dispose());
|
this.sashItems.forEach(i => i.disposable.dispose());
|
||||||
|
|
|
@ -17,5 +17,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.hc-black .monaco-toolbar .action-label.toolbar-toggle-more {
|
.hc-black .monaco-toolbar .action-label.toolbar-toggle-more {
|
||||||
background-image: url('ellipsis-dark.svg');
|
background-image: url('ellipsis-hc.svg');
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import * as errors from 'vs/base/common/errors';
|
||||||
import * as uuid from 'vs/base/common/uuid';
|
import * as uuid from 'vs/base/common/uuid';
|
||||||
import { networkInterfaces } from 'os';
|
import { networkInterfaces } from 'os';
|
||||||
import { TernarySearchTree } from 'vs/base/common/map';
|
import { TernarySearchTree } from 'vs/base/common/map';
|
||||||
|
import { getMac } from 'vs/base/node/macAddress';
|
||||||
|
|
||||||
// http://www.techrepublic.com/blog/data-center/mac-address-scorecard-for-common-virtual-machine-platforms/
|
// http://www.techrepublic.com/blog/data-center/mac-address-scorecard-for-common-virtual-machine-platforms/
|
||||||
// VMware ESX 3, Server, Workstation, Player 00-50-56, 00-0C-29, 00-05-69
|
// VMware ESX 3, Server, Workstation, Player 00-50-56, 00-0C-29, 00-05-69
|
||||||
|
@ -76,35 +77,25 @@ export const virtualMachineHint: { value(): number } = new class {
|
||||||
};
|
};
|
||||||
|
|
||||||
let machineId: Promise<string>;
|
let machineId: Promise<string>;
|
||||||
export function getMachineId(): Promise<string> {
|
export async function getMachineId(): Promise<string> {
|
||||||
return machineId || (machineId = getMacMachineId()
|
if (!machineId) {
|
||||||
.then(id => id || uuid.generateUuid())); // fallback, generate a UUID
|
machineId = (async () => {
|
||||||
|
const id = await getMacMachineId();
|
||||||
|
|
||||||
|
return id || uuid.generateUuid(); // fallback, generate a UUID
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
return machineId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMacMachineId(): Promise<string> {
|
async function getMacMachineId(): Promise<string | undefined> {
|
||||||
return new Promise<string>(resolve => {
|
try {
|
||||||
Promise.all([import('crypto'), import('getmac')]).then(([crypto, getmac]) => {
|
const crypto = await import('crypto');
|
||||||
try {
|
const macAddress = await getMac();
|
||||||
getmac.getMac((error, macAddress) => {
|
return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex');
|
||||||
if (!error) {
|
} catch (err) {
|
||||||
resolve(crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex'));
|
errors.onUnexpectedError(err);
|
||||||
} else {
|
return undefined;
|
||||||
resolve(undefined);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Timeout due to hang with reduced privileges #58392
|
|
||||||
// TODO@sbatten: Remove this when getmac is patched
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve(undefined);
|
|
||||||
}, 10000);
|
|
||||||
} catch (err) {
|
|
||||||
errors.onUnexpectedError(err);
|
|
||||||
resolve(undefined);
|
|
||||||
}
|
|
||||||
}, err => {
|
|
||||||
errors.onUnexpectedError(err);
|
|
||||||
resolve(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
69
src/vs/base/node/macAddress.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import { isWindows } from 'vs/base/common/platform';
|
||||||
|
|
||||||
|
const cmdline = {
|
||||||
|
windows: 'getmac.exe',
|
||||||
|
unix: '/sbin/ifconfig -a || /sbin/ip link'
|
||||||
|
};
|
||||||
|
|
||||||
|
const invalidMacAddresses = [
|
||||||
|
'00:00:00:00:00:00',
|
||||||
|
'ff:ff:ff:ff:ff:ff',
|
||||||
|
'ac:de:48:00:11:22'
|
||||||
|
];
|
||||||
|
|
||||||
|
function validateMacAddress(candidate: string): boolean {
|
||||||
|
let tempCandidate = candidate.replace(/\-/g, ':').toLowerCase();
|
||||||
|
for (let invalidMacAddress of invalidMacAddresses) {
|
||||||
|
if (invalidMacAddress === tempCandidate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMac(): Promise<string> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const timeout = setTimeout(() => reject('Unable to retrieve mac address (timeout after 10s)'), 10000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
resolve(await doGetMac());
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function doGetMac(): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
exec(isWindows ? cmdline.windows : cmdline.unix, { timeout: 10000 }, (err, stdout, stdin) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(`Unable to retrieve mac address (${err.toString()})`);
|
||||||
|
} else {
|
||||||
|
const regex = /(?:[a-f\d]{2}[:\-]){5}[a-f\d]{2}/gi;
|
||||||
|
|
||||||
|
let match;
|
||||||
|
while ((match = regex.exec(stdout)) !== null) {
|
||||||
|
const macAddressCandidate = match[0];
|
||||||
|
if (validateMacAddress(macAddressCandidate)) {
|
||||||
|
return resolve(macAddressCandidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reject('Unable to retrieve mac address (unexpected format)');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as getmac from 'getmac';
|
|
||||||
import { getMachineId } from 'vs/base/node/id';
|
import { getMachineId } from 'vs/base/node/id';
|
||||||
|
import { getMac } from 'vs/base/node/macAddress';
|
||||||
|
|
||||||
suite('ID', () => {
|
suite('ID', () => {
|
||||||
|
|
||||||
|
@ -16,9 +16,7 @@ suite('ID', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getMac', () => {
|
test('getMac', () => {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return getMac().then(macAddress => {
|
||||||
getmac.getMac((err, macAddress) => err ? reject(err) : resolve(macAddress));
|
|
||||||
}).then(macAddress => {
|
|
||||||
assert.ok(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(macAddress), `Expected a MAC address, got: ${macAddress}`);
|
assert.ok(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(macAddress), `Expected a MAC address, got: ${macAddress}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { EnvironmentService } from 'vs/platform/environment/node/environmentServ
|
||||||
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
|
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
|
||||||
import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
||||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
|
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
||||||
import { IRequestService } from 'vs/platform/request/common/request';
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
|
@ -55,6 +55,8 @@ import { FileService } from 'vs/platform/files/common/fileService';
|
||||||
import { IFileService } from 'vs/platform/files/common/files';
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
|
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
|
||||||
import { Schemas } from 'vs/base/common/network';
|
import { Schemas } from 'vs/base/common/network';
|
||||||
|
import { IProductService } from 'vs/platform/product/common/product';
|
||||||
|
import { ProductService } from 'vs/platform/product/node/productService';
|
||||||
|
|
||||||
export interface ISharedProcessConfiguration {
|
export interface ISharedProcessConfiguration {
|
||||||
readonly machineId: string;
|
readonly machineId: string;
|
||||||
|
@ -114,6 +116,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
|
||||||
services.set(IConfigurationService, configurationService);
|
services.set(IConfigurationService, configurationService);
|
||||||
services.set(IRequestService, new SyncDescriptor(RequestService));
|
services.set(IRequestService, new SyncDescriptor(RequestService));
|
||||||
services.set(IDownloadService, new SyncDescriptor(DownloadService));
|
services.set(IDownloadService, new SyncDescriptor(DownloadService));
|
||||||
|
services.set(IProductService, new SyncDescriptor(ProductService));
|
||||||
|
|
||||||
const mainProcessService = new MainProcessService(server, mainRouter);
|
const mainProcessService = new MainProcessService(server, mainRouter);
|
||||||
services.set(IMainProcessService, mainProcessService);
|
services.set(IMainProcessService, mainProcessService);
|
||||||
|
|
|
@ -90,6 +90,7 @@ import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemPro
|
||||||
export class CodeApplication extends Disposable {
|
export class CodeApplication extends Disposable {
|
||||||
|
|
||||||
private static readonly MACHINE_ID_KEY = 'telemetry.machineId';
|
private static readonly MACHINE_ID_KEY = 'telemetry.machineId';
|
||||||
|
private static readonly TRUE_MACHINE_ID_KEY = 'telemetry.trueMachineId';
|
||||||
|
|
||||||
private windowsMainService: IWindowsMainService | undefined;
|
private windowsMainService: IWindowsMainService | undefined;
|
||||||
|
|
||||||
|
@ -363,8 +364,8 @@ export class CodeApplication extends Disposable {
|
||||||
|
|
||||||
// Resolve unique machine ID
|
// Resolve unique machine ID
|
||||||
this.logService.trace('Resolving machine identifier...');
|
this.logService.trace('Resolving machine identifier...');
|
||||||
const machineId = await this.resolveMachineId();
|
const { machineId, trueMachineId } = await this.resolveMachineId();
|
||||||
this.logService.trace(`Resolved machine identifier: ${machineId}`);
|
this.logService.trace(`Resolved machine identifier: ${machineId} (trueMachineId: ${trueMachineId})`);
|
||||||
|
|
||||||
// Spawn shared process after the first window has opened and 3s have passed
|
// Spawn shared process after the first window has opened and 3s have passed
|
||||||
const sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId, this.userEnv);
|
const sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId, this.userEnv);
|
||||||
|
@ -378,7 +379,7 @@ export class CodeApplication extends Disposable {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
const appInstantiationService = await this.createServices(machineId, sharedProcess, sharedProcessClient);
|
const appInstantiationService = await this.createServices(machineId, trueMachineId, sharedProcess, sharedProcessClient);
|
||||||
|
|
||||||
// Create driver
|
// Create driver
|
||||||
if (this.environmentService.driverHandle) {
|
if (this.environmentService.driverHandle) {
|
||||||
|
@ -404,7 +405,7 @@ export class CodeApplication extends Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async resolveMachineId(): Promise<string> {
|
private async resolveMachineId(): Promise<{ machineId: string, trueMachineId?: string }> {
|
||||||
|
|
||||||
// We cache the machineId for faster lookups on startup
|
// We cache the machineId for faster lookups on startup
|
||||||
// and resolve it only once initially if not cached
|
// and resolve it only once initially if not cached
|
||||||
|
@ -415,10 +416,21 @@ export class CodeApplication extends Disposable {
|
||||||
this.stateService.setItem(CodeApplication.MACHINE_ID_KEY, machineId);
|
this.stateService.setItem(CodeApplication.MACHINE_ID_KEY, machineId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return machineId;
|
// Check if machineId is hashed iBridge Device
|
||||||
|
let trueMachineId: string | undefined;
|
||||||
|
if (isMacintosh && machineId === '6c9d2bc8f91b89624add29c0abeae7fb42bf539fa1cdb2e3e57cd668fa9bcead') {
|
||||||
|
trueMachineId = this.stateService.getItem<string>(CodeApplication.TRUE_MACHINE_ID_KEY);
|
||||||
|
if (!trueMachineId) {
|
||||||
|
trueMachineId = await getMachineId();
|
||||||
|
|
||||||
|
this.stateService.setItem(CodeApplication.TRUE_MACHINE_ID_KEY, trueMachineId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { machineId, trueMachineId };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createServices(machineId: string, sharedProcess: SharedProcess, sharedProcessClient: Promise<Client<string>>): Promise<IInstantiationService> {
|
private async createServices(machineId: string, trueMachineId: string | undefined, sharedProcess: SharedProcess, sharedProcessClient: Promise<Client<string>>): Promise<IInstantiationService> {
|
||||||
const services = new ServiceCollection();
|
const services = new ServiceCollection();
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
|
@ -473,7 +485,7 @@ export class CodeApplication extends Disposable {
|
||||||
const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(this.logService));
|
const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(this.logService));
|
||||||
const commonProperties = resolveCommonProperties(product.commit, pkg.version, machineId, this.environmentService.installSourcePath);
|
const commonProperties = resolveCommonProperties(product.commit, pkg.version, machineId, this.environmentService.installSourcePath);
|
||||||
const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath];
|
const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath];
|
||||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths };
|
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, trueMachineId };
|
||||||
|
|
||||||
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config]));
|
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config]));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -21,10 +21,12 @@ import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/worksp
|
||||||
import { IBackupMainService } from 'vs/platform/backup/common/backup';
|
import { IBackupMainService } from 'vs/platform/backup/common/backup';
|
||||||
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
|
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
|
||||||
import * as perf from 'vs/base/common/performance';
|
import * as perf from 'vs/base/common/performance';
|
||||||
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService';
|
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||||
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
|
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
|
||||||
import { endsWith } from 'vs/base/common/strings';
|
import { endsWith } from 'vs/base/common/strings';
|
||||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||||
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
|
import pkg from 'vs/platform/product/node/package';
|
||||||
|
|
||||||
const RUN_TEXTMATE_IN_WORKER = false;
|
const RUN_TEXTMATE_IN_WORKER = false;
|
||||||
|
|
||||||
|
@ -76,6 +78,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||||
config: IWindowCreationOptions,
|
config: IWindowCreationOptions,
|
||||||
@ILogService private readonly logService: ILogService,
|
@ILogService private readonly logService: ILogService,
|
||||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||||
|
@IFileService private readonly fileService: IFileService,
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
@IThemeMainService private readonly themeMainService: IThemeMainService,
|
@IThemeMainService private readonly themeMainService: IThemeMainService,
|
||||||
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
||||||
|
@ -307,7 +310,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||||
private handleMarketplaceRequests(): void {
|
private handleMarketplaceRequests(): void {
|
||||||
|
|
||||||
// Resolve marketplace headers
|
// Resolve marketplace headers
|
||||||
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(this.environmentService);
|
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(pkg.version, this.environmentService, this.fileService);
|
||||||
|
|
||||||
// Inject headers when requests are incoming
|
// Inject headers when requests are incoming
|
||||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||||
|
|
|
@ -207,46 +207,17 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
|
||||||
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this);
|
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this);
|
||||||
|
|
||||||
this.lifecycleService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
|
this.lifecycleService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
|
||||||
this.lifecycleService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.setupNativeHelpers());
|
this.lifecycleService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex());
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupNativeHelpers(): void {
|
private installWindowsMutex(): void {
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
|
|
||||||
// Setup Windows mutex
|
|
||||||
try {
|
try {
|
||||||
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
|
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
|
||||||
const mutex = new WindowsMutex(product.win32MutexName);
|
const mutex = new WindowsMutex(product.win32MutexName);
|
||||||
once(this.lifecycleService.onWillShutdown)(() => mutex.release());
|
once(this.lifecycleService.onWillShutdown)(() => mutex.release());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
|
|
||||||
if (!this.environmentService.isBuilt) {
|
|
||||||
this.showMessageBox({
|
|
||||||
title: product.nameLong,
|
|
||||||
type: 'warning',
|
|
||||||
message: 'Failed to load windows-mutex!',
|
|
||||||
detail: e.toString(),
|
|
||||||
noLink: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dev only: Ensure Windows foreground love module is present
|
|
||||||
if (!this.environmentService.isBuilt) {
|
|
||||||
try {
|
|
||||||
require.__$__nodeRequire('windows-foreground-love');
|
|
||||||
} catch (e) {
|
|
||||||
this.logService.error(e);
|
|
||||||
|
|
||||||
this.showMessageBox({
|
|
||||||
title: product.nameLong,
|
|
||||||
type: 'warning',
|
|
||||||
message: 'Failed to load windows-foreground-love!',
|
|
||||||
detail: e.toString(),
|
|
||||||
noLink: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/
|
||||||
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||||
import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
||||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
|
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
import { combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||||
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
|
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
|
||||||
|
@ -46,6 +46,8 @@ import { FileService } from 'vs/platform/files/common/fileService';
|
||||||
import { IFileService } from 'vs/platform/files/common/files';
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
|
import { IProductService } from 'vs/platform/product/common/product';
|
||||||
|
import { ProductService } from 'vs/platform/product/node/productService';
|
||||||
|
|
||||||
const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id);
|
const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id);
|
||||||
const notInstalled = (id: string) => localize('notInstalled', "Extension '{0}' is not installed.", id);
|
const notInstalled = (id: string) => localize('notInstalled', "Extension '{0}' is not installed.", id);
|
||||||
|
@ -301,6 +303,7 @@ export async function main(argv: ParsedArgs): Promise<void> {
|
||||||
services.set(ILogService, logService);
|
services.set(ILogService, logService);
|
||||||
services.set(IConfigurationService, configurationService);
|
services.set(IConfigurationService, configurationService);
|
||||||
services.set(IStateService, new SyncDescriptor(StateService));
|
services.set(IStateService, new SyncDescriptor(StateService));
|
||||||
|
services.set(IProductService, new SyncDescriptor(ProductService));
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
const fileService = new FileService(logService);
|
const fileService = new FileService(logService);
|
||||||
|
|
28
src/vs/code/test/electron-main/nativeHelpers.test.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { isWindows } from 'vs/base/common/platform';
|
||||||
|
|
||||||
|
suite('Windows Native Helpers', () => {
|
||||||
|
test('windows-mutex', async () => {
|
||||||
|
if (!isWindows) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mutex = await import('windows-mutex');
|
||||||
|
assert.ok(mutex, 'Unable to load windows-mutex dependency.');
|
||||||
|
assert.ok(typeof mutex.isActive === 'function', 'Unable to load windows-mutex dependency.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('windows-foreground-love', async () => {
|
||||||
|
if (!isWindows) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const foregroundLove = await import('windows-foreground-love');
|
||||||
|
assert.ok(foregroundLove, 'Unable to load windows-foreground-love dependency.');
|
||||||
|
});
|
||||||
|
});
|
|
@ -80,7 +80,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
||||||
this._ui.update(newState);
|
this._ui.update(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showCodeActions(actions: Promise<CodeActionSet>, at: IAnchor | IPosition) {
|
public showCodeActions(actions: CodeActionSet, at: IAnchor | IPosition) {
|
||||||
return this._ui.showCodeActionList(actions, at);
|
return this._ui.showCodeActionList(actions, at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,15 +95,7 @@ export class CodeActionUi extends Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async showCodeActionList(codeActions: Promise<CodeActionSet>, at?: IAnchor | IPosition): Promise<void> {
|
public async showCodeActionList(actions: CodeActionSet, at?: IAnchor | IPosition): Promise<void> {
|
||||||
let actions: CodeActionSet;
|
|
||||||
try {
|
|
||||||
actions = await codeActions;
|
|
||||||
} catch (e) {
|
|
||||||
onUnexpectedError(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._codeActionWidget.show(actions, at);
|
this._codeActionWidget.show(actions, at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { Position } from 'vs/editor/common/core/position';
|
import { Position } from 'vs/editor/common/core/position';
|
||||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||||
import { DocumentColorProvider, Hover as MarkdownHover, HoverProviderRegistry, IColor, CodeAction } from 'vs/editor/common/modes';
|
import { DocumentColorProvider, Hover as MarkdownHover, HoverProviderRegistry, IColor } from 'vs/editor/common/modes';
|
||||||
import { getColorPresentations } from 'vs/editor/contrib/colorPicker/color';
|
import { getColorPresentations } from 'vs/editor/contrib/colorPicker/color';
|
||||||
import { ColorDetector } from 'vs/editor/contrib/colorPicker/colorDetector';
|
import { ColorDetector } from 'vs/editor/contrib/colorPicker/colorDetector';
|
||||||
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/colorPickerModel';
|
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/colorPickerModel';
|
||||||
|
@ -517,21 +517,6 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||||
const hoverElement = $('div.hover-row.status-bar');
|
const hoverElement = $('div.hover-row.status-bar');
|
||||||
const disposables = new DisposableStore();
|
const disposables = new DisposableStore();
|
||||||
const actionsElement = dom.append(hoverElement, $('div.actions'));
|
const actionsElement = dom.append(hoverElement, $('div.actions'));
|
||||||
disposables.add(this.renderAction(actionsElement, {
|
|
||||||
label: nls.localize('quick fixes', "Quick Fix..."),
|
|
||||||
commandId: QuickFixAction.Id,
|
|
||||||
run: async (target) => {
|
|
||||||
const codeActionsPromise = this.getCodeActions(markerHover.marker);
|
|
||||||
disposables.add(toDisposable(() => codeActionsPromise.cancel()));
|
|
||||||
|
|
||||||
const controller = QuickFixController.get(this._editor);
|
|
||||||
const elementPosition = dom.getDomNodePagePosition(target);
|
|
||||||
controller.showCodeActions(codeActionsPromise, {
|
|
||||||
x: elementPosition.left + 6,
|
|
||||||
y: elementPosition.top + elementPosition.height + 6
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) {
|
if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) {
|
||||||
disposables.add(this.renderAction(actionsElement, {
|
disposables.add(this.renderAction(actionsElement, {
|
||||||
label: nls.localize('peek problem', "Peek Problem"),
|
label: nls.localize('peek problem', "Peek Problem"),
|
||||||
|
@ -543,27 +528,61 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const quickfixPlaceholderElement = dom.append(actionsElement, $('div'));
|
||||||
|
quickfixPlaceholderElement.style.opacity = '0';
|
||||||
|
quickfixPlaceholderElement.style.transition = 'opacity 0.2s';
|
||||||
|
setTimeout(() => quickfixPlaceholderElement.style.opacity = '1', 200);
|
||||||
|
quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes...");
|
||||||
|
disposables.add(toDisposable(() => quickfixPlaceholderElement.remove()));
|
||||||
|
|
||||||
|
|
||||||
|
const codeActionsPromise = this.getCodeActions(markerHover.marker);
|
||||||
|
disposables.add(toDisposable(() => codeActionsPromise.cancel()));
|
||||||
|
codeActionsPromise.then(actions => {
|
||||||
|
quickfixPlaceholderElement.style.transition = '';
|
||||||
|
quickfixPlaceholderElement.style.opacity = '1';
|
||||||
|
|
||||||
|
if (!actions.actions.length) {
|
||||||
|
actions.dispose();
|
||||||
|
quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
quickfixPlaceholderElement.remove();
|
||||||
|
|
||||||
|
let showing = false;
|
||||||
|
disposables.add(toDisposable(() => {
|
||||||
|
if (!showing) {
|
||||||
|
actions.dispose();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
disposables.add(this.renderAction(actionsElement, {
|
||||||
|
label: nls.localize('quick fixes', "Quick Fix..."),
|
||||||
|
commandId: QuickFixAction.Id,
|
||||||
|
run: (target) => {
|
||||||
|
showing = true;
|
||||||
|
const controller = QuickFixController.get(this._editor);
|
||||||
|
const elementPosition = dom.getDomNodePagePosition(target);
|
||||||
|
controller.showCodeActions(actions, {
|
||||||
|
x: elementPosition.left + 6,
|
||||||
|
y: elementPosition.top + elementPosition.height + 6
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
this.renderDisposable.value = disposables;
|
this.renderDisposable.value = disposables;
|
||||||
return hoverElement;
|
return hoverElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCodeActions(marker: IMarker): CancelablePromise<CodeActionSet> {
|
private getCodeActions(marker: IMarker): CancelablePromise<CodeActionSet> {
|
||||||
const noAction: CodeAction = {
|
return createCancelablePromise(cancellationToken => {
|
||||||
title: nls.localize('editor.action.quickFix.noneMessage', "No code actions available"),
|
return getCodeActions(
|
||||||
kind: CodeActionKind.QuickFix.value,
|
|
||||||
};
|
|
||||||
return createCancelablePromise(async (cancellationToken): Promise<CodeActionSet> => {
|
|
||||||
const result = await getCodeActions(
|
|
||||||
this._editor.getModel()!,
|
this._editor.getModel()!,
|
||||||
new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn),
|
new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn),
|
||||||
{ type: 'manual', filter: { kind: CodeActionKind.QuickFix } },
|
{ type: 'manual', filter: { kind: CodeActionKind.QuickFix } },
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
return {
|
|
||||||
actions: result.actions.length ? result.actions : [noAction],
|
|
||||||
hasAutoFix: result.hasAutoFix,
|
|
||||||
dispose: () => result.dispose(),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { tmpdir } from 'os';
|
|
||||||
import * as path from 'vs/base/common/path';
|
|
||||||
import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/common/errors';
|
import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/common/errors';
|
||||||
import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
|
@ -12,11 +10,8 @@ import { assign, getOrDefault } from 'vs/base/common/objects';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IPager } from 'vs/base/common/paging';
|
import { IPager } from 'vs/base/common/paging';
|
||||||
import { IRequestService, IRequestOptions, IRequestContext, asJson, asText } from 'vs/platform/request/common/request';
|
import { IRequestService, IRequestOptions, IRequestContext, asJson, asText } from 'vs/platform/request/common/request';
|
||||||
import pkg from 'vs/platform/product/node/package';
|
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
|
||||||
import product from 'vs/platform/product/node/product';
|
|
||||||
import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator';
|
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { writeFileSync, readFile } from 'vs/base/node/pfs';
|
|
||||||
import { generateUuid, isUUID } from 'vs/base/common/uuid';
|
import { generateUuid, isUUID } from 'vs/base/common/uuid';
|
||||||
import { values } from 'vs/base/common/map';
|
import { values } from 'vs/base/common/map';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
@ -24,6 +19,9 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||||
import { IFileService } from 'vs/platform/files/common/files';
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { joinPath } from 'vs/base/common/resources';
|
||||||
|
import { VSBuffer } from 'vs/base/common/buffer';
|
||||||
|
import { IProductService } from 'vs/platform/product/common/product';
|
||||||
|
|
||||||
interface IRawGalleryExtensionFile {
|
interface IRawGalleryExtensionFile {
|
||||||
assetType: string;
|
assetType: string;
|
||||||
|
@ -339,11 +337,12 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||||
@IFileService private readonly fileService: IFileService,
|
@IFileService private readonly fileService: IFileService,
|
||||||
|
@IProductService private readonly productService: IProductService,
|
||||||
) {
|
) {
|
||||||
const config = product.extensionsGallery;
|
const config = productService.extensionsGallery;
|
||||||
this.extensionsGalleryUrl = config && config.serviceUrl;
|
this.extensionsGalleryUrl = config && config.serviceUrl;
|
||||||
this.extensionsControlUrl = config && config.controlUrl;
|
this.extensionsControlUrl = config && config.controlUrl;
|
||||||
this.commonHeadersPromise = resolveMarketplaceHeaders(this.environmentService);
|
this.commonHeadersPromise = resolveMarketplaceHeaders(productService.version, this.environmentService, this.fileService);
|
||||||
}
|
}
|
||||||
|
|
||||||
private api(path = ''): string {
|
private api(path = ''): string {
|
||||||
|
@ -356,7 +355,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
|
|
||||||
getCompatibleExtension(arg1: IExtensionIdentifier | IGalleryExtension, version?: string): Promise<IGalleryExtension | null> {
|
getCompatibleExtension(arg1: IExtensionIdentifier | IGalleryExtension, version?: string): Promise<IGalleryExtension | null> {
|
||||||
const extension: IGalleryExtension | null = isIExtensionIdentifier(arg1) ? null : arg1;
|
const extension: IGalleryExtension | null = isIExtensionIdentifier(arg1) ? null : arg1;
|
||||||
if (extension && extension.properties.engine && isEngineValid(extension.properties.engine)) {
|
if (extension && extension.properties.engine && isEngineValid(extension.properties.engine, this.productService.version)) {
|
||||||
return Promise.resolve(extension);
|
return Promise.resolve(extension);
|
||||||
}
|
}
|
||||||
const { id, uuid } = extension ? extension.identifier : <IExtensionIdentifier>arg1;
|
const { id, uuid } = extension ? extension.identifier : <IExtensionIdentifier>arg1;
|
||||||
|
@ -382,7 +381,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
const versionAsset = rawExtension.versions.filter(v => v.version === version)[0];
|
const versionAsset = rawExtension.versions.filter(v => v.version === version)[0];
|
||||||
if (versionAsset) {
|
if (versionAsset) {
|
||||||
const extension = toExtension(rawExtension, versionAsset, 0, query);
|
const extension = toExtension(rawExtension, versionAsset, 0, query);
|
||||||
if (extension.properties.engine && isEngineValid(extension.properties.engine)) {
|
if (extension.properties.engine && isEngineValid(extension.properties.engine, this.productService.version)) {
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,9 +534,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
download(extension: IGalleryExtension, operation: InstallOperation): Promise<string> {
|
download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise<URI> {
|
||||||
this.logService.trace('ExtensionGalleryService#download', extension.identifier.id);
|
this.logService.trace('ExtensionGalleryService#download', extension.identifier.id);
|
||||||
const zipPath = path.join(tmpdir(), generateUuid());
|
const zip = joinPath(location, generateUuid());
|
||||||
const data = getGalleryExtensionTelemetryData(extension);
|
const data = getGalleryExtensionTelemetryData(extension);
|
||||||
const startTime = new Date().getTime();
|
const startTime = new Date().getTime();
|
||||||
/* __GDPR__
|
/* __GDPR__
|
||||||
|
@ -557,9 +556,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
} : extension.assets.download;
|
} : extension.assets.download;
|
||||||
|
|
||||||
return this.getAsset(downloadAsset)
|
return this.getAsset(downloadAsset)
|
||||||
.then(context => this.fileService.writeFile(URI.file(zipPath), context.stream))
|
.then(context => this.fileService.writeFile(zip, context.stream))
|
||||||
.then(() => log(new Date().getTime() - startTime))
|
.then(() => log(new Date().getTime() - startTime))
|
||||||
.then(() => zipPath);
|
.then(() => zip);
|
||||||
}
|
}
|
||||||
|
|
||||||
getReadme(extension: IGalleryExtension, token: CancellationToken): Promise<string> {
|
getReadme(extension: IGalleryExtension, token: CancellationToken): Promise<string> {
|
||||||
|
@ -615,7 +614,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
return this.queryGallery(query, CancellationToken.None).then(({ galleryExtensions }) => {
|
return this.queryGallery(query, CancellationToken.None).then(({ galleryExtensions }) => {
|
||||||
if (galleryExtensions.length) {
|
if (galleryExtensions.length) {
|
||||||
if (compatible) {
|
if (compatible) {
|
||||||
return Promise.all(galleryExtensions[0].versions.map(v => this.getEngine(v).then(engine => isEngineValid(engine) ? v : null)))
|
return Promise.all(galleryExtensions[0].versions.map(v => this.getEngine(v).then(engine => isEngineValid(engine, this.productService.version) ? v : null)))
|
||||||
.then(versions => versions
|
.then(versions => versions
|
||||||
.filter(v => !!v)
|
.filter(v => !!v)
|
||||||
.map(v => ({ version: v!.version, date: v!.lastUpdated })));
|
.map(v => ({ version: v!.version, date: v!.lastUpdated })));
|
||||||
|
@ -701,7 +700,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isEngineValid(engine)) {
|
if (isEngineValid(engine, this.productService.version)) {
|
||||||
return Promise.resolve(version);
|
return Promise.resolve(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,7 +732,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
const version = versions[0];
|
const version = versions[0];
|
||||||
return this.getEngine(version)
|
return this.getEngine(version)
|
||||||
.then(engine => {
|
.then(engine => {
|
||||||
if (!isEngineValid(engine)) {
|
if (!isEngineValid(engine, this.productService.version)) {
|
||||||
return this.getLastValidExtensionVersionRecursively(extension, versions.slice(1));
|
return this.getLastValidExtensionVersionRecursively(extension, versions.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,24 +773,30 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveMarketplaceHeaders(environmentService: IEnvironmentService): Promise<{ [key: string]: string; }> {
|
export async function resolveMarketplaceHeaders(version: string, environmentService: IEnvironmentService, fileService: IFileService): Promise<{ [key: string]: string; }> {
|
||||||
const marketplaceMachineIdFile = path.join(environmentService.userDataPath, 'machineid');
|
const marketplaceMachineIdFile = joinPath(URI.file(environmentService.userDataPath), 'machineid');
|
||||||
|
|
||||||
return readFile(marketplaceMachineIdFile, 'utf8')
|
let uuid: string | null = null;
|
||||||
.then<string | null>(contents => isUUID(contents) ? contents : null, () => null /* error reading ID file */)
|
|
||||||
.then(uuid => {
|
try {
|
||||||
if (!uuid) {
|
const contents = await fileService.readFile(marketplaceMachineIdFile);
|
||||||
uuid = generateUuid();
|
const value = contents.value.toString();
|
||||||
try {
|
uuid = isUUID(value) ? value : null;
|
||||||
writeFileSync(marketplaceMachineIdFile, uuid);
|
} catch (e) {
|
||||||
} catch (error) {
|
uuid = null;
|
||||||
//noop
|
}
|
||||||
}
|
|
||||||
}
|
if (!uuid) {
|
||||||
return {
|
uuid = generateUuid();
|
||||||
'X-Market-Client-Id': `VSCode ${pkg.version}`,
|
try {
|
||||||
'User-Agent': `VSCode ${pkg.version}`,
|
await fileService.writeFile(marketplaceMachineIdFile, VSBuffer.fromString(uuid));
|
||||||
'X-Market-User-Id': uuid
|
} catch (error) {
|
||||||
};
|
//noop
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'X-Market-Client-Id': `VSCode ${version}`,
|
||||||
|
'User-Agent': `VSCode ${version}`,
|
||||||
|
'X-Market-User-Id': uuid
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -151,7 +151,7 @@ export interface IExtensionGalleryService {
|
||||||
isEnabled(): boolean;
|
isEnabled(): boolean;
|
||||||
query(token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
query(token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
||||||
query(options: IQueryOptions, token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
query(options: IQueryOptions, token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
||||||
download(extension: IGalleryExtension, operation: InstallOperation): Promise<string>;
|
download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise<URI>;
|
||||||
reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise<void>;
|
reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise<void>;
|
||||||
getReadme(extension: IGalleryExtension, token: CancellationToken): Promise<string>;
|
getReadme(extension: IGalleryExtension, token: CancellationToken): Promise<string>;
|
||||||
getManifest(extension: IGalleryExtension, token: CancellationToken): Promise<IExtensionManifest | null>;
|
getManifest(extension: IGalleryExtension, token: CancellationToken): Promise<IExtensionManifest | null>;
|
||||||
|
|
|
@ -35,7 +35,7 @@ import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/ex
|
||||||
import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle';
|
import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle';
|
||||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator';
|
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
|
||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||||
|
@ -197,7 +197,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||||
.then(manifest => {
|
.then(manifest => {
|
||||||
const identifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
|
const identifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
|
||||||
let operation: InstallOperation = InstallOperation.Install;
|
let operation: InstallOperation = InstallOperation.Install;
|
||||||
if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode)) {
|
if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, pkg.version)) {
|
||||||
return Promise.reject(new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", identifier.id, pkg.version)));
|
return Promise.reject(new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", identifier.id, pkg.version)));
|
||||||
}
|
}
|
||||||
const identifierWithVersion = new ExtensionIdentifierWithVersion(identifier, manifest.version);
|
const identifierWithVersion = new ExtensionIdentifierWithVersion(identifier, manifest.version);
|
||||||
|
@ -391,9 +391,10 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||||
};
|
};
|
||||||
|
|
||||||
this.logService.trace('Started downloading extension:', extension.identifier.id);
|
this.logService.trace('Started downloading extension:', extension.identifier.id);
|
||||||
return this.galleryService.download(extension, operation)
|
return this.galleryService.download(extension, URI.file(tmpdir()), operation)
|
||||||
.then(
|
.then(
|
||||||
zipPath => {
|
zip => {
|
||||||
|
const zipPath = zip.fsPath;
|
||||||
this.logService.info('Downloaded extension:', extension.identifier.id, zipPath);
|
this.logService.info('Downloaded extension:', extension.identifier.id, zipPath);
|
||||||
return getManifest(zipPath)
|
return getManifest(zipPath)
|
||||||
.then(
|
.then(
|
||||||
|
|
|
@ -10,15 +10,32 @@ import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||||
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||||
import { join } from 'vs/base/common/path';
|
import { join } from 'vs/base/common/path';
|
||||||
import { mkdirp, RimRafMode, rimraf } from 'vs/base/node/pfs';
|
import { mkdirp, RimRafMode, rimraf } from 'vs/base/node/pfs';
|
||||||
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService';
|
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||||
import { isUUID } from 'vs/base/common/uuid';
|
import { isUUID } from 'vs/base/common/uuid';
|
||||||
|
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
|
import { FileService } from 'vs/platform/files/common/fileService';
|
||||||
|
import { NullLogService } from 'vs/platform/log/common/log';
|
||||||
|
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||||
|
import { Schemas } from 'vs/base/common/network';
|
||||||
|
import pkg from 'vs/platform/product/node/package';
|
||||||
|
|
||||||
suite('Extension Gallery Service', () => {
|
suite('Extension Gallery Service', () => {
|
||||||
const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extensiongalleryservice');
|
const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'extensiongalleryservice');
|
||||||
const marketplaceHome = join(parentDir, 'Marketplace');
|
const marketplaceHome = join(parentDir, 'Marketplace');
|
||||||
|
let fileService: IFileService;
|
||||||
|
let disposables: DisposableStore;
|
||||||
|
|
||||||
setup(done => {
|
setup(done => {
|
||||||
|
|
||||||
|
disposables = new DisposableStore();
|
||||||
|
fileService = new FileService(new NullLogService());
|
||||||
|
disposables.add(fileService);
|
||||||
|
|
||||||
|
const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService());
|
||||||
|
disposables.add(diskFileSystemProvider);
|
||||||
|
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
|
||||||
|
|
||||||
// Delete any existing backups completely and then re-create it.
|
// Delete any existing backups completely and then re-create it.
|
||||||
rimraf(marketplaceHome, RimRafMode.MOVE).then(() => {
|
rimraf(marketplaceHome, RimRafMode.MOVE).then(() => {
|
||||||
mkdirp(marketplaceHome).then(() => {
|
mkdirp(marketplaceHome).then(() => {
|
||||||
|
@ -28,6 +45,7 @@ suite('Extension Gallery Service', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
teardown(done => {
|
teardown(done => {
|
||||||
|
disposables.clear();
|
||||||
rimraf(marketplaceHome, RimRafMode.MOVE).then(done, done);
|
rimraf(marketplaceHome, RimRafMode.MOVE).then(done, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,10 +53,10 @@ suite('Extension Gallery Service', () => {
|
||||||
const args = ['--user-data-dir', marketplaceHome];
|
const args = ['--user-data-dir', marketplaceHome];
|
||||||
const environmentService = new EnvironmentService(parseArgs(args), process.execPath);
|
const environmentService = new EnvironmentService(parseArgs(args), process.execPath);
|
||||||
|
|
||||||
return resolveMarketplaceHeaders(environmentService).then(headers => {
|
return resolveMarketplaceHeaders(pkg.version, environmentService, fileService).then(headers => {
|
||||||
assert.ok(isUUID(headers['X-Market-User-Id']));
|
assert.ok(isUUID(headers['X-Market-User-Id']));
|
||||||
|
|
||||||
return resolveMarketplaceHeaders(environmentService).then(headers2 => {
|
return resolveMarketplaceHeaders(pkg.version, environmentService, fileService).then(headers2 => {
|
||||||
assert.equal(headers['X-Market-User-Id'], headers2['X-Market-User-Id']);
|
assert.equal(headers['X-Market-User-Id'], headers2['X-Market-User-Id']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import pkg from 'vs/platform/product/node/package';
|
|
||||||
|
|
||||||
export interface IParsedVersion {
|
export interface IParsedVersion {
|
||||||
hasCaret: boolean;
|
hasCaret: boolean;
|
||||||
|
@ -222,9 +221,9 @@ export function isValidExtensionVersion(version: string, extensionDesc: IReduced
|
||||||
return isVersionValid(version, extensionDesc.engines.vscode, notices);
|
return isVersionValid(version, extensionDesc.engines.vscode, notices);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isEngineValid(engine: string): boolean {
|
export function isEngineValid(engine: string, version: string): boolean {
|
||||||
// TODO@joao: discuss with alex '*' doesn't seem to be a valid engine version
|
// TODO@joao: discuss with alex '*' doesn't seem to be a valid engine version
|
||||||
return engine === '*' || isVersionValid(pkg.version, engine);
|
return engine === '*' || isVersionValid(version, engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVersionValid(currentVersion: string, requestedVersion: string, notices: string[] = []): boolean {
|
export function isVersionValid(currentVersion: string, requestedVersion: string, notices: string[] = []): boolean {
|
|
@ -3,7 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { INormalizedVersion, IParsedVersion, IReducedExtensionDescription, isValidExtensionVersion, isValidVersion, isValidVersionStr, normalizeVersion, parseVersion } from 'vs/platform/extensions/node/extensionValidator';
|
import { INormalizedVersion, IParsedVersion, IReducedExtensionDescription, isValidExtensionVersion, isValidVersion, isValidVersionStr, normalizeVersion, parseVersion } from 'vs/platform/extensions/common/extensionValidator';
|
||||||
|
|
||||||
suite('Extension Version Validator', () => {
|
suite('Extension Version Validator', () => {
|
||||||
|
|
||||||
|
|
|
@ -1696,7 +1696,9 @@ suite('Disk File Service', () => {
|
||||||
assert.ok(!error);
|
assert.ok(!error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file', done => {
|
const runWatchTests = isLinux;
|
||||||
|
|
||||||
|
(runWatchTests ? test : test.skip)('watch - file', done => {
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
|
||||||
|
@ -1705,11 +1707,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes'), 50);
|
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes'), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file symbolic link', async done => {
|
(runWatchTests && !isWindows /* symbolic links not reliable on windows */ ? test : test.skip)('watch - file symbolic link', async done => {
|
||||||
if (isWindows) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const toWatch = URI.file(join(testDir, 'lorem.txt-linked'));
|
const toWatch = URI.file(join(testDir, 'lorem.txt-linked'));
|
||||||
await symlink(join(testDir, 'lorem.txt'), toWatch.fsPath);
|
await symlink(join(testDir, 'lorem.txt'), toWatch.fsPath);
|
||||||
|
|
||||||
|
@ -1718,11 +1716,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes'), 50);
|
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes'), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file - multiple writes', done => {
|
(runWatchTests ? test : test.skip)('watch - file - multiple writes', done => {
|
||||||
if (isWindows) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
|
||||||
|
@ -1733,7 +1727,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes 3'), 20);
|
setTimeout(() => writeFileSync(toWatch.fsPath, 'Changes 3'), 20);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file - delete file', done => {
|
(runWatchTests ? test : test.skip)('watch - file - delete file', done => {
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
|
||||||
|
@ -1742,11 +1736,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => unlinkSync(toWatch.fsPath), 50);
|
setTimeout(() => unlinkSync(toWatch.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file - rename file', done => {
|
(runWatchTests ? test : test.skip)('watch - file - rename file', done => {
|
||||||
if (isWindows) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
||||||
const toWatchRenamed = URI.file(join(testDir, 'index-watch1-renamed.html'));
|
const toWatchRenamed = URI.file(join(testDir, 'index-watch1-renamed.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
@ -1756,7 +1746,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => renameSync(toWatch.fsPath, toWatchRenamed.fsPath), 50);
|
setTimeout(() => renameSync(toWatch.fsPath, toWatchRenamed.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file - rename file (different case)', done => {
|
(runWatchTests ? test : test.skip)('watch - file - rename file (different case)', done => {
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch1.html'));
|
||||||
const toWatchRenamed = URI.file(join(testDir, 'INDEX-watch1.html'));
|
const toWatchRenamed = URI.file(join(testDir, 'INDEX-watch1.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
@ -1770,7 +1760,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => renameSync(toWatch.fsPath, toWatchRenamed.fsPath), 50);
|
setTimeout(() => renameSync(toWatch.fsPath, toWatchRenamed.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - file (atomic save)', function (done) {
|
(runWatchTests ? test : test.skip)('watch - file (atomic save)', function (done) {
|
||||||
const toWatch = URI.file(join(testDir, 'index-watch2.html'));
|
const toWatch = URI.file(join(testDir, 'index-watch2.html'));
|
||||||
writeFileSync(toWatch.fsPath, 'Init');
|
writeFileSync(toWatch.fsPath, 'Init');
|
||||||
|
|
||||||
|
@ -1786,11 +1776,7 @@ suite('Disk File Service', () => {
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - change file', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - change file', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch3'));
|
const watchDir = URI.file(join(testDir, 'watch3'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1802,11 +1788,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - add file', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - add file', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch4'));
|
const watchDir = URI.file(join(testDir, 'watch4'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1817,11 +1799,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - delete file', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - delete file', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch5'));
|
const watchDir = URI.file(join(testDir, 'watch5'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1833,11 +1811,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => unlinkSync(file.fsPath), 50);
|
setTimeout(() => unlinkSync(file.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - add folder', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - add folder', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch6'));
|
const watchDir = URI.file(join(testDir, 'watch6'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1848,11 +1822,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => mkdirSync(folder.fsPath), 50);
|
setTimeout(() => mkdirSync(folder.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - delete folder', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - delete folder', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch7'));
|
const watchDir = URI.file(join(testDir, 'watch7'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1864,11 +1834,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => rimrafSync(folder.fsPath), 50);
|
setTimeout(() => rimrafSync(folder.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - symbolic link - change file', async done => {
|
(runWatchTests && !isWindows /* symbolic links not reliable on windows */ ? test : test.skip)('watch - folder (non recursive) - symbolic link - change file', async done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'deep-link'));
|
const watchDir = URI.file(join(testDir, 'deep-link'));
|
||||||
await symlink(join(testDir, 'deep'), watchDir.fsPath);
|
await symlink(join(testDir, 'deep'), watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1880,11 +1846,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
setTimeout(() => writeFileSync(file.fsPath, 'Changes'), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - rename file', done => {
|
(runWatchTests ? test : test.skip)('watch - folder (non recursive) - rename file', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch8'));
|
const watchDir = URI.file(join(testDir, 'watch8'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
@ -1898,11 +1860,7 @@ suite('Disk File Service', () => {
|
||||||
setTimeout(() => renameSync(file.fsPath, fileRenamed.fsPath), 50);
|
setTimeout(() => renameSync(file.fsPath, fileRenamed.fsPath), 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('watch - folder (non recursive) - rename file (different case)', done => {
|
(runWatchTests && isLinux /* this test requires a case sensitive file system */ ? test : test.skip)('watch - folder (non recursive) - rename file (different case)', done => {
|
||||||
if (!isLinux) {
|
|
||||||
return done(); // watch tests are flaky on other platforms
|
|
||||||
}
|
|
||||||
|
|
||||||
const watchDir = URI.file(join(testDir, 'watch8'));
|
const watchDir = URI.file(join(testDir, 'watch8'));
|
||||||
mkdirSync(watchDir.fsPath);
|
mkdirSync(watchDir.fsPath);
|
||||||
|
|
||||||
|
|
|
@ -38,4 +38,10 @@ export class ProductService implements IProductService {
|
||||||
get settingsSearchBuildId(): number | undefined { return this.productConfiguration ? this.productConfiguration.settingsSearchBuildId : undefined; }
|
get settingsSearchBuildId(): number | undefined { return this.productConfiguration ? this.productConfiguration.settingsSearchBuildId : undefined; }
|
||||||
|
|
||||||
get settingsSearchUrl(): string | undefined { return this.productConfiguration ? this.productConfiguration.settingsSearchUrl : undefined; }
|
get settingsSearchUrl(): string | undefined { return this.productConfiguration ? this.productConfiguration.settingsSearchUrl : undefined; }
|
||||||
|
|
||||||
|
get experimentsUrl(): string | undefined { return this.productConfiguration ? this.productConfiguration.experimentsUrl : undefined; }
|
||||||
|
|
||||||
|
get extensionKeywords(): { [extension: string]: readonly string[]; } | undefined { return this.productConfiguration ? this.productConfiguration.extensionKeywords : undefined; }
|
||||||
|
|
||||||
|
get extensionAllowedBadgeProviders(): readonly string[] | undefined { return this.productConfiguration ? this.productConfiguration.extensionAllowedBadgeProviders : undefined; }
|
||||||
}
|
}
|
|
@ -33,6 +33,10 @@ export interface IProductService {
|
||||||
|
|
||||||
readonly settingsSearchBuildId?: number;
|
readonly settingsSearchBuildId?: number;
|
||||||
readonly settingsSearchUrl?: string;
|
readonly settingsSearchUrl?: string;
|
||||||
|
|
||||||
|
readonly experimentsUrl?: string;
|
||||||
|
readonly extensionKeywords?: { [extension: string]: readonly string[]; };
|
||||||
|
readonly extensionAllowedBadgeProviders?: readonly string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
|
|
|
@ -33,4 +33,10 @@ export class ProductService implements IProductService {
|
||||||
get settingsSearchBuildId(): number | undefined { return product.settingsSearchBuildId; }
|
get settingsSearchBuildId(): number | undefined { return product.settingsSearchBuildId; }
|
||||||
|
|
||||||
get settingsSearchUrl(): string | undefined { return product.settingsSearchUrl; }
|
get settingsSearchUrl(): string | undefined { return product.settingsSearchUrl; }
|
||||||
|
|
||||||
|
get experimentsUrl(): string | undefined { return product.experimentsUrl; }
|
||||||
|
|
||||||
|
get extensionKeywords(): { [extension: string]: readonly string[]; } | undefined { return product.extensionKeywords; }
|
||||||
|
|
||||||
|
get extensionAllowedBadgeProviders(): readonly string[] | undefined { return product.extensionAllowedBadgeProviders; }
|
||||||
}
|
}
|
|
@ -12,22 +12,24 @@ import { VSBufferReadableStream, streamToBuffer } from 'vs/base/common/buffer';
|
||||||
|
|
||||||
export const IRequestService = createDecorator<IRequestService>('requestService');
|
export const IRequestService = createDecorator<IRequestService>('requestService');
|
||||||
|
|
||||||
|
export interface IHeaders {
|
||||||
|
[header: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IRequestOptions {
|
export interface IRequestOptions {
|
||||||
type?: string;
|
type?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
user?: string;
|
user?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
headers?: any;
|
headers?: IHeaders;
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
data?: string;
|
data?: string;
|
||||||
followRedirects?: number;
|
followRedirects?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRequestContext {
|
export interface IRequestContext {
|
||||||
// req: http.ClientRequest;
|
|
||||||
// res: http.ClientResponse;
|
|
||||||
res: {
|
res: {
|
||||||
headers: { [n: string]: string };
|
headers: IHeaders;
|
||||||
statusCode?: number;
|
statusCode?: number;
|
||||||
};
|
};
|
||||||
stream: VSBufferReadableStream;
|
stream: VSBufferReadableStream;
|
||||||
|
|
51
src/vs/platform/request/common/requestIpc.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||||
|
import { Event } from 'vs/base/common/event';
|
||||||
|
import { IRequestService, IRequestOptions, IRequestContext, IHeaders } from 'vs/platform/request/common/request';
|
||||||
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
import { VSBuffer, bufferToStream, streamToBuffer } from 'vs/base/common/buffer';
|
||||||
|
|
||||||
|
type RequestResponse = [
|
||||||
|
{
|
||||||
|
headers: IHeaders;
|
||||||
|
statusCode?: number;
|
||||||
|
},
|
||||||
|
VSBuffer
|
||||||
|
];
|
||||||
|
|
||||||
|
export class RequestChannel implements IServerChannel {
|
||||||
|
|
||||||
|
constructor(private readonly service: IRequestService) { }
|
||||||
|
|
||||||
|
listen(context: any, event: string): Event<any> {
|
||||||
|
throw new Error('Invalid listen');
|
||||||
|
}
|
||||||
|
|
||||||
|
call(context: any, command: string, args?: any): Promise<any> {
|
||||||
|
switch (command) {
|
||||||
|
case 'request': return this.service.request(args[0], CancellationToken.None)
|
||||||
|
.then(async ({ res, stream }) => {
|
||||||
|
const buffer = await streamToBuffer(stream);
|
||||||
|
return <RequestResponse>[{ statusCode: res.statusCode, headers: res.headers }, buffer];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw new Error('Invalid call');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RequestChannelClient {
|
||||||
|
|
||||||
|
_serviceBrand: any;
|
||||||
|
|
||||||
|
constructor(private readonly channel: IChannel) { }
|
||||||
|
|
||||||
|
async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||||
|
const [res, buffer] = await this.channel.call<RequestResponse>('request', [options]);
|
||||||
|
return { res, stream: bufferToStream(buffer) };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { instanceStorageKey, firstSessionDateStorageKey, lastSessionDateStorageKey, currentSessionDateStorageKey } from 'vs/platform/telemetry/node/workbenchCommonProperties';
|
import { instanceStorageKey, firstSessionDateStorageKey, lastSessionDateStorageKey, currentSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
|
||||||
type Key = string;
|
type Key = string;
|
||||||
type Value = string;
|
type Value = string;
|
||||||
|
|
|
@ -38,3 +38,9 @@ export interface ITelemetryService {
|
||||||
|
|
||||||
isOptedIn: boolean;
|
isOptedIn: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keys
|
||||||
|
export const instanceStorageKey = 'telemetry.instanceId';
|
||||||
|
export const currentSessionDateStorageKey = 'telemetry.currentSessionDate';
|
||||||
|
export const firstSessionDateStorageKey = 'telemetry.firstSessionDate';
|
||||||
|
export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
|
|
@ -19,6 +19,7 @@ export interface ITelemetryServiceConfig {
|
||||||
appender: ITelemetryAppender;
|
appender: ITelemetryAppender;
|
||||||
commonProperties?: Promise<{ [name: string]: any }>;
|
commonProperties?: Promise<{ [name: string]: any }>;
|
||||||
piiPaths?: string[];
|
piiPaths?: string[];
|
||||||
|
trueMachineId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TelemetryService implements ITelemetryService {
|
export class TelemetryService implements ITelemetryService {
|
||||||
|
@ -74,6 +75,15 @@ export class TelemetryService implements ITelemetryService {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
this.publicLog('machineIdFallback', { usingFallbackGuid: !isHashedId });
|
this.publicLog('machineIdFallback', { usingFallbackGuid: !isHashedId });
|
||||||
|
|
||||||
|
if (config.trueMachineId) {
|
||||||
|
/* __GDPR__
|
||||||
|
"machineIdDisambiguation" : {
|
||||||
|
"correctedMachineId" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this.publicLog('machineIdDisambiguation', { correctedMachineId: config.trueMachineId });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,7 @@
|
||||||
|
|
||||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||||
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
|
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
|
||||||
|
import { instanceStorageKey, firstSessionDateStorageKey, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||||
export const instanceStorageKey = 'telemetry.instanceId';
|
|
||||||
export const currentSessionDateStorageKey = 'telemetry.currentSessionDate';
|
|
||||||
export const firstSessionDateStorageKey = 'telemetry.firstSessionDate';
|
|
||||||
export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
|
|
||||||
|
|
||||||
export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string, remoteAuthority?: string): Promise<{ [name: string]: string | undefined }> {
|
export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string, remoteAuthority?: string): Promise<{ [name: string]: string | undefined }> {
|
||||||
const result = await resolveCommonProperties(commit, version, machineId, installSourcePath);
|
const result = await resolveCommonProperties(commit, version, machineId, installSourcePath);
|
||||||
|
|
5
src/vs/vscode.proposed.d.ts
vendored
|
@ -1084,8 +1084,11 @@ declare module 'vscode' {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement to handle when the terminal is ready to start firing events.
|
* Implement to handle when the terminal is ready to start firing events.
|
||||||
|
*
|
||||||
|
* @param initialDimensions The dimensions of the terminal, this will be undefined if the
|
||||||
|
* terminal panel has not been opened before this is called.
|
||||||
*/
|
*/
|
||||||
start?(): void;
|
start?(initialDimensions: TerminalDimensions | undefined): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -88,7 +88,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
|
||||||
|
|
||||||
const disposables = new DisposableStore();
|
const disposables = new DisposableStore();
|
||||||
|
|
||||||
const webview = this._webviewService.createWebview({
|
const webview = this._webviewService.createWebview('' + handle, {
|
||||||
enableFindWidget: false,
|
enableFindWidget: false,
|
||||||
allowSvgs: false,
|
allowSvgs: false,
|
||||||
extension: { id: extensionId, location: URI.revive(extensionLocation) }
|
extension: { id: extensionId, location: URI.revive(extensionLocation) }
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IAvailableShellsRequest, IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal';
|
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IAvailableShellsRequest, IDefaultShellAndArgsRequest, ITerminalVirtualProcessRequest } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto, TerminalLaunchConfig } from 'vs/workbench/api/common/extHost.protocol';
|
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto, TerminalLaunchConfig, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||||
|
@ -48,7 +48,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||||
this._toDispose.add(_terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
|
this._toDispose.add(_terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
|
||||||
this._toDispose.add(_terminalService.onInstanceMaximumDimensionsChanged(instance => this._onInstanceMaximumDimensionsChanged(instance)));
|
this._toDispose.add(_terminalService.onInstanceMaximumDimensionsChanged(instance => this._onInstanceMaximumDimensionsChanged(instance)));
|
||||||
this._toDispose.add(_terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request)));
|
this._toDispose.add(_terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request)));
|
||||||
this._toDispose.add(_terminalService.onInstanceRequestVirtualProcess(proxy => this._onTerminalRequestVirtualProcess(proxy)));
|
this._toDispose.add(_terminalService.onInstanceRequestVirtualProcess(e => this._onTerminalRequestVirtualProcess(e)));
|
||||||
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : null)));
|
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : null)));
|
||||||
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
|
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
|
||||||
this._toDispose.add(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
|
this._toDispose.add(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
|
||||||
|
@ -244,12 +244,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ready = this._terminalProcessesReady[request.proxy.terminalId];
|
const proxy = request.proxy;
|
||||||
|
const ready = this._terminalProcessesReady[proxy.terminalId];
|
||||||
if (ready) {
|
if (ready) {
|
||||||
ready(request.proxy);
|
ready(proxy);
|
||||||
delete this._terminalProcessesReady[request.proxy.terminalId];
|
delete this._terminalProcessesReady[proxy.terminalId];
|
||||||
} else {
|
} else {
|
||||||
this._terminalProcesses[request.proxy.terminalId] = Promise.resolve(request.proxy);
|
this._terminalProcesses[proxy.terminalId] = Promise.resolve(proxy);
|
||||||
}
|
}
|
||||||
const shellLaunchConfigDto: ShellLaunchConfigDto = {
|
const shellLaunchConfigDto: ShellLaunchConfigDto = {
|
||||||
name: request.shellLaunchConfig.name,
|
name: request.shellLaunchConfig.name,
|
||||||
|
@ -258,16 +259,17 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||||
cwd: request.shellLaunchConfig.cwd,
|
cwd: request.shellLaunchConfig.cwd,
|
||||||
env: request.shellLaunchConfig.env
|
env: request.shellLaunchConfig.env
|
||||||
};
|
};
|
||||||
this._proxy.$createProcess(request.proxy.terminalId, shellLaunchConfigDto, request.activeWorkspaceRootUri, request.cols, request.rows, request.isWorkspaceShellAllowed);
|
this._proxy.$createProcess(proxy.terminalId, shellLaunchConfigDto, request.activeWorkspaceRootUri, request.cols, request.rows, request.isWorkspaceShellAllowed);
|
||||||
request.proxy.onInput(data => this._proxy.$acceptProcessInput(request.proxy.terminalId, data));
|
proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data));
|
||||||
request.proxy.onResize(dimensions => this._proxy.$acceptProcessResize(request.proxy.terminalId, dimensions.cols, dimensions.rows));
|
proxy.onResize(dimensions => this._proxy.$acceptProcessResize(proxy.terminalId, dimensions.cols, dimensions.rows));
|
||||||
request.proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(request.proxy.terminalId, immediate));
|
proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
|
||||||
request.proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(request.proxy.terminalId));
|
proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(proxy.terminalId));
|
||||||
request.proxy.onRequestInitialCwd(() => this._proxy.$acceptProcessRequestInitialCwd(request.proxy.terminalId));
|
proxy.onRequestInitialCwd(() => this._proxy.$acceptProcessRequestInitialCwd(proxy.terminalId));
|
||||||
request.proxy.onRequestLatency(() => this._onRequestLatency(request.proxy.terminalId));
|
proxy.onRequestLatency(() => this._onRequestLatency(proxy.terminalId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onTerminalRequestVirtualProcess(proxy: ITerminalProcessExtHostProxy): void {
|
private _onTerminalRequestVirtualProcess(request: ITerminalVirtualProcessRequest): void {
|
||||||
|
const proxy = request.proxy;
|
||||||
const ready = this._terminalProcessesReady[proxy.terminalId];
|
const ready = this._terminalProcessesReady[proxy.terminalId];
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
this._terminalProcesses[proxy.terminalId] = Promise.resolve(proxy);
|
this._terminalProcesses[proxy.terminalId] = Promise.resolve(proxy);
|
||||||
|
@ -278,6 +280,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||||
|
|
||||||
// Note that onReisze is not being listened to here as it needs to fire when max dimensions
|
// Note that onReisze is not being listened to here as it needs to fire when max dimensions
|
||||||
// change, excluding the dimension override
|
// change, excluding the dimension override
|
||||||
|
const initialDimensions: ITerminalDimensionsDto | undefined = request.cols && request.rows ? {
|
||||||
|
columns: request.cols,
|
||||||
|
rows: request.rows
|
||||||
|
} : undefined;
|
||||||
|
this._proxy.$startVirtualProcess(proxy.terminalId, initialDimensions);
|
||||||
proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data));
|
proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data));
|
||||||
proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
|
proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
|
||||||
proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(proxy.terminalId));
|
proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(proxy.terminalId));
|
||||||
|
|
|
@ -93,7 +93,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||||
mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
|
mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
const webview = this._webviewEditorService.createWebview(this.getInternalWebviewId(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), {
|
const webview = this._webviewEditorService.createWebview(handle, this.getInternalWebviewViewType(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), {
|
||||||
location: URI.revive(extensionLocation),
|
location: URI.revive(extensionLocation),
|
||||||
id: extensionId
|
id: extensionId
|
||||||
}, this.createWebviewEventDelegate(handle)) as WebviewEditorInput<MainThreadWebviewState>;
|
}, this.createWebviewEventDelegate(handle)) as WebviewEditorInput<MainThreadWebviewState>;
|
||||||
|
@ -212,7 +212,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||||
this._revivers.delete(viewType);
|
this._revivers.delete(viewType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getInternalWebviewId(viewType: string): string {
|
private getInternalWebviewViewType(viewType: string): string {
|
||||||
return `mainThreadWebview-${viewType}`;
|
return `mainThreadWebview-${viewType}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1135,6 +1135,11 @@ export interface IShellAndArgsDto {
|
||||||
args: string[] | string | undefined;
|
args: string[] | string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ITerminalDimensionsDto {
|
||||||
|
columns: number;
|
||||||
|
rows: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExtHostTerminalServiceShape {
|
export interface ExtHostTerminalServiceShape {
|
||||||
$acceptTerminalClosed(id: number): void;
|
$acceptTerminalClosed(id: number): void;
|
||||||
$acceptTerminalOpened(id: number, name: string): void;
|
$acceptTerminalOpened(id: number, name: string): void;
|
||||||
|
@ -1146,6 +1151,7 @@ export interface ExtHostTerminalServiceShape {
|
||||||
$acceptTerminalDimensions(id: number, cols: number, rows: number): void;
|
$acceptTerminalDimensions(id: number, cols: number, rows: number): void;
|
||||||
$acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void;
|
$acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void;
|
||||||
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
||||||
|
$startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void;
|
||||||
$acceptProcessInput(id: number, data: string): void;
|
$acceptProcessInput(id: number, data: string): void;
|
||||||
$acceptProcessResize(id: number, cols: number, rows: number): void;
|
$acceptProcessResize(id: number, cols: number, rows: number): void;
|
||||||
$acceptProcessShutdown(id: number, immediate: boolean): void;
|
$acceptProcessShutdown(id: number, immediate: boolean): void;
|
||||||
|
|
|
@ -40,7 +40,7 @@ export class ExtHostWebview implements vscode.Webview {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get cspSource(): string {
|
public get cspSource(): string {
|
||||||
return this._initData.webviewCspSource;
|
return this._initData.webviewCspSource.replace('{{uuid}}', this._handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get html(): string {
|
public get html(): string {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
import * as platform from 'vs/base/common/platform';
|
import * as platform from 'vs/base/common/platform';
|
||||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
|
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||||
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment, ITerminalChildProcess, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment, ITerminalChildProcess, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||||
|
@ -329,10 +329,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||||
public createVirtualProcessTerminal(options: vscode.TerminalVirtualProcessOptions): vscode.Terminal {
|
public createVirtualProcessTerminal(options: vscode.TerminalVirtualProcessOptions): vscode.Terminal {
|
||||||
const terminal = new ExtHostTerminal(this._proxy, options.name);
|
const terminal = new ExtHostTerminal(this._proxy, options.name);
|
||||||
const p = new ExtHostVirtualProcess(options.virtualProcess);
|
const p = new ExtHostVirtualProcess(options.virtualProcess);
|
||||||
terminal.createVirtualProcess().then(() => {
|
terminal.createVirtualProcess().then(() => this._setupExtHostProcessListeners(terminal._id, p));
|
||||||
this._setupExtHostProcessListeners(terminal._id, p);
|
|
||||||
p.startSendingEvents();
|
|
||||||
});
|
|
||||||
this._terminals.push(terminal);
|
this._terminals.push(terminal);
|
||||||
return terminal;
|
return terminal;
|
||||||
}
|
}
|
||||||
|
@ -344,7 +341,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||||
}
|
}
|
||||||
const p = new ExtHostVirtualProcess(virtualProcess);
|
const p = new ExtHostVirtualProcess(virtualProcess);
|
||||||
this._setupExtHostProcessListeners(id, p);
|
this._setupExtHostProcessListeners(id, p);
|
||||||
p.startSendingEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createTerminalRenderer(name: string): vscode.TerminalRenderer {
|
public createTerminalRenderer(name: string): vscode.TerminalRenderer {
|
||||||
|
@ -585,6 +581,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||||
this._setupExtHostProcessListeners(id, new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, enableConpty, this._logService));
|
this._setupExtHostProcessListeners(id, new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, enableConpty, this._logService));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void {
|
||||||
|
(this._terminalProcesses[id] as ExtHostVirtualProcess).startSendingEvents(initialDimensions);
|
||||||
|
}
|
||||||
|
|
||||||
private _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): void {
|
private _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): void {
|
||||||
p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd));
|
p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd));
|
||||||
p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
|
p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
|
||||||
|
@ -779,7 +779,7 @@ class ExtHostVirtualProcess implements ITerminalChildProcess {
|
||||||
return Promise.resolve(0);
|
return Promise.resolve(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
startSendingEvents(): void {
|
startSendingEvents(initialDimensions: ITerminalDimensionsDto | undefined): void {
|
||||||
// Flush all buffered events
|
// Flush all buffered events
|
||||||
this._queuedEvents.forEach(e => (<any>e.emitter.fire)(e.data));
|
this._queuedEvents.forEach(e => (<any>e.emitter.fire)(e.data));
|
||||||
this._queuedEvents = [];
|
this._queuedEvents = [];
|
||||||
|
@ -798,7 +798,7 @@ class ExtHostVirtualProcess implements ITerminalChildProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._virtualProcess.start) {
|
if (this._virtualProcess.start) {
|
||||||
this._virtualProcess.start();
|
this._virtualProcess.start(initialDimensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,9 @@ import { joinPath } from 'vs/base/common/resources';
|
||||||
import { BrowserStorageService } from 'vs/platform/storage/browser/storageService';
|
import { BrowserStorageService } from 'vs/platform/storage/browser/storageService';
|
||||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
|
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
|
import { RequestService } from 'vs/workbench/services/request/browser/requestService';
|
||||||
|
import { InMemoryUserDataProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider';
|
||||||
|
|
||||||
class CodeRendererMain extends Disposable {
|
class CodeRendererMain extends Disposable {
|
||||||
|
|
||||||
|
@ -155,12 +158,14 @@ class CodeRendererMain extends Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User Data Provider
|
if (!userDataProvider) {
|
||||||
if (userDataProvider) {
|
userDataProvider = this._register(new InMemoryUserDataProvider());
|
||||||
fileService.registerProvider(Schemas.userData, userDataProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const services = await Promise.all([
|
// User Data Provider
|
||||||
|
fileService.registerProvider(Schemas.userData, userDataProvider);
|
||||||
|
|
||||||
|
const [configurationService, storageService] = await Promise.all([
|
||||||
this.createWorkspaceService(payload, environmentService, fileService, remoteAgentService, logService).then(service => {
|
this.createWorkspaceService(payload, environmentService, fileService, remoteAgentService, logService).then(service => {
|
||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
|
@ -181,7 +186,10 @@ class CodeRendererMain extends Disposable {
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return { serviceCollection, logService, storageService: services[1] };
|
// Request Service
|
||||||
|
serviceCollection.set(IRequestService, new RequestService(this.configuration.requestHandler, remoteAgentService, configurationService, logService));
|
||||||
|
|
||||||
|
return { serviceCollection, logService, storageService };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IWorkbenchEnvironmentService, fileService: IFileService, logService: ILogService): Promise<BrowserStorageService> {
|
private async createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IWorkbenchEnvironmentService, fileService: IFileService, logService: ILogService): Promise<BrowserStorageService> {
|
||||||
|
|
|
@ -11,9 +11,8 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||||
// tslint:disable-next-line: import-patterns no-standalone-editor
|
// tslint:disable-next-line: import-patterns no-standalone-editor
|
||||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { IExtensionGalleryService, IQueryOptions, IGalleryExtension, InstallOperation, StatisticType, ITranslation, IGalleryExtensionVersion, IExtensionIdentifier, IReportedExtension, IExtensionManagementService, ILocalExtension, IGalleryMetadata, IExtensionTipsService, ExtensionRecommendationReason, IExtensionRecommendation, IExtensionEnablementService, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IGalleryExtension, IExtensionIdentifier, IReportedExtension, IExtensionManagementService, ILocalExtension, IGalleryMetadata, IExtensionTipsService, ExtensionRecommendationReason, IExtensionRecommendation, IExtensionEnablementService, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { IPager } from 'vs/base/common/paging';
|
import { ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions';
|
||||||
import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions';
|
|
||||||
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
|
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
|
||||||
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { ConsoleLogService, ILogService } from 'vs/platform/log/common/log';
|
import { ConsoleLogService, ILogService } from 'vs/platform/log/common/log';
|
||||||
|
@ -29,7 +28,6 @@ import { ITunnelService } from 'vs/platform/remote/common/tunnel';
|
||||||
import { IReloadSessionEvent, IExtensionHostDebugService, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent } from 'vs/workbench/services/extensions/common/extensionHostDebug';
|
import { IReloadSessionEvent, IExtensionHostDebugService, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent } from 'vs/workbench/services/extensions/common/extensionHostDebug';
|
||||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||||
// tslint:disable-next-line: import-patterns
|
// tslint:disable-next-line: import-patterns
|
||||||
// tslint:disable-next-line: import-patterns
|
|
||||||
import { IExtensionsWorkbenchService, IExtension as IExtension2 } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtensionsWorkbenchService, IExtension as IExtension2 } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||||
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||||
|
@ -41,6 +39,8 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||||
import { toStoreData, restoreRecentlyOpened } from 'vs/platform/history/common/historyStorage';
|
import { toStoreData, restoreRecentlyOpened } from 'vs/platform/history/common/historyStorage';
|
||||||
|
// tslint:disable-next-line: import-patterns
|
||||||
|
import { IExperimentService, IExperiment, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
|
|
||||||
//#region Download
|
//#region Download
|
||||||
|
|
||||||
|
@ -58,74 +58,6 @@ registerSingleton(IDownloadService, SimpleDownloadService, true);
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Extension Gallery
|
|
||||||
|
|
||||||
export class SimpleExtensionGalleryService implements IExtensionGalleryService {
|
|
||||||
|
|
||||||
_serviceBrand: any;
|
|
||||||
|
|
||||||
isEnabled(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
query(token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
|
||||||
query(options: IQueryOptions, token: CancellationToken): Promise<IPager<IGalleryExtension>>;
|
|
||||||
query(arg1: any, arg2?: any): Promise<IPager<IGalleryExtension>> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
download(extension: IGalleryExtension, operation: InstallOperation): Promise<string> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise<void> {
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getReadme(extension: IGalleryExtension, token: CancellationToken): Promise<string> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getManifest(extension: IGalleryExtension, token: CancellationToken): Promise<IExtensionManifest> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise<string> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise<ITranslation> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise<IGalleryExtensionVersion[]> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getExtensionsReport(): Promise<IReportedExtension[]> {
|
|
||||||
// @ts-ignore
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
getCompatibleExtension(extension: IGalleryExtension): Promise<IGalleryExtension>;
|
|
||||||
getCompatibleExtension(id: IExtensionIdentifier, version?: string): Promise<IGalleryExtension>;
|
|
||||||
getCompatibleExtension(id: any, version?: any) {
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerSingleton(IExtensionGalleryService, SimpleExtensionGalleryService, true);
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#endregion IExtensionsWorkbenchService
|
//#endregion IExtensionsWorkbenchService
|
||||||
export class SimpleExtensionsWorkbenchService implements IExtensionsWorkbenchService {
|
export class SimpleExtensionsWorkbenchService implements IExtensionsWorkbenchService {
|
||||||
_serviceBrand: any;
|
_serviceBrand: any;
|
||||||
|
@ -1066,3 +998,34 @@ class SimpleTunnelService implements ITunnelService {
|
||||||
registerSingleton(ITunnelService, SimpleTunnelService);
|
registerSingleton(ITunnelService, SimpleTunnelService);
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region experiments
|
||||||
|
|
||||||
|
class ExperimentService implements IExperimentService {
|
||||||
|
_serviceBrand: any;
|
||||||
|
|
||||||
|
async getExperimentById(id: string): Promise<IExperiment> {
|
||||||
|
return {
|
||||||
|
enabled: false,
|
||||||
|
id: '',
|
||||||
|
state: ExperimentState.NoRun
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getExperimentsByType(type: ExperimentActionType): Promise<IExperiment[]> {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCuratedExtensionsList(curatedExtensionsKey: string): Promise<string[]> {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
markAsCompleted(experimentId: string): void { }
|
||||||
|
|
||||||
|
onExperimentEnabled: Event<IExperiment> = Event.None;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
registerSingleton(IExperimentService, ExperimentService);
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { Event } from 'vs/base/common/event';
|
||||||
|
|
||||||
|
export const enum ExperimentState {
|
||||||
|
Evaluating,
|
||||||
|
NoRun,
|
||||||
|
Run,
|
||||||
|
Complete
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExperimentAction {
|
||||||
|
type: ExperimentActionType;
|
||||||
|
properties: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ExperimentActionType {
|
||||||
|
Custom = 'Custom',
|
||||||
|
Prompt = 'Prompt',
|
||||||
|
AddToRecommendations = 'AddToRecommendations',
|
||||||
|
ExtensionSearchResults = 'ExtensionSearchResults'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LocalizedPromptText = { [locale: string]: string; };
|
||||||
|
|
||||||
|
export interface IExperimentActionPromptProperties {
|
||||||
|
promptText: string | LocalizedPromptText;
|
||||||
|
commands: IExperimentActionPromptCommand[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExperimentActionPromptCommand {
|
||||||
|
text: string | { [key: string]: string };
|
||||||
|
externalLink?: string;
|
||||||
|
curatedExtensionsKey?: string;
|
||||||
|
curatedExtensionsList?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExperiment {
|
||||||
|
id: string;
|
||||||
|
enabled: boolean;
|
||||||
|
state: ExperimentState;
|
||||||
|
action?: IExperimentAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExperimentService {
|
||||||
|
_serviceBrand: any;
|
||||||
|
getExperimentById(id: string): Promise<IExperiment>;
|
||||||
|
getExperimentsByType(type: ExperimentActionType): Promise<IExperiment[]>;
|
||||||
|
getCuratedExtensionsList(curatedExtensionsKey: string): Promise<string[]>;
|
||||||
|
markAsCompleted(experimentId: string): void;
|
||||||
|
|
||||||
|
onExperimentEnabled: Event<IExperiment>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IExperimentService = createDecorator<IExperimentService>('experimentService');
|
|
@ -3,12 +3,9 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import product from 'vs/platform/product/node/product';
|
|
||||||
|
|
||||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
|
||||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
|
@ -21,8 +18,9 @@ import { ITextFileService, StateChange } from 'vs/workbench/services/textfile/co
|
||||||
import { WorkspaceStats } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
|
import { WorkspaceStats } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { distinct } from 'vs/base/common/arrays';
|
import { distinct } from 'vs/base/common/arrays';
|
||||||
import { lastSessionDateStorageKey } from 'vs/platform/telemetry/node/workbenchCommonProperties';
|
|
||||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||||
|
import { ExperimentState, IExperimentAction, IExperimentService, IExperiment, ExperimentActionType, IExperimentActionPromptProperties } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
|
import { IProductService } from 'vs/platform/product/common/product';
|
||||||
|
|
||||||
interface IExperimentStorageState {
|
interface IExperimentStorageState {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
@ -31,13 +29,6 @@ interface IExperimentStorageState {
|
||||||
lastEditedDate?: string;
|
lastEditedDate?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum ExperimentState {
|
|
||||||
Evaluating,
|
|
||||||
NoRun,
|
|
||||||
Run,
|
|
||||||
Complete
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRawExperiment {
|
interface IRawExperiment {
|
||||||
id: string;
|
id: string;
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
|
@ -64,51 +55,6 @@ interface IRawExperiment {
|
||||||
action?: IExperimentAction;
|
action?: IExperimentAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IExperimentAction {
|
|
||||||
type: ExperimentActionType;
|
|
||||||
properties: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ExperimentActionType {
|
|
||||||
Custom = 'Custom',
|
|
||||||
Prompt = 'Prompt',
|
|
||||||
AddToRecommendations = 'AddToRecommendations',
|
|
||||||
ExtensionSearchResults = 'ExtensionSearchResults'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LocalizedPromptText = { [locale: string]: string; };
|
|
||||||
|
|
||||||
export interface IExperimentActionPromptProperties {
|
|
||||||
promptText: string | LocalizedPromptText;
|
|
||||||
commands: IExperimentActionPromptCommand[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IExperimentActionPromptCommand {
|
|
||||||
text: string | { [key: string]: string };
|
|
||||||
externalLink?: string;
|
|
||||||
curatedExtensionsKey?: string;
|
|
||||||
curatedExtensionsList?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IExperiment {
|
|
||||||
id: string;
|
|
||||||
enabled: boolean;
|
|
||||||
state: ExperimentState;
|
|
||||||
action?: IExperimentAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IExperimentService {
|
|
||||||
_serviceBrand: any;
|
|
||||||
getExperimentById(id: string): Promise<IExperiment>;
|
|
||||||
getExperimentsByType(type: ExperimentActionType): Promise<IExperiment[]>;
|
|
||||||
getCuratedExtensionsList(curatedExtensionsKey: string): Promise<string[]>;
|
|
||||||
markAsCompleted(experimentId: string): void;
|
|
||||||
|
|
||||||
onExperimentEnabled: Event<IExperiment>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IExperimentService = createDecorator<IExperimentService>('experimentService');
|
|
||||||
|
|
||||||
export class ExperimentService extends Disposable implements IExperimentService {
|
export class ExperimentService extends Disposable implements IExperimentService {
|
||||||
_serviceBrand: any;
|
_serviceBrand: any;
|
||||||
private _experiments: IExperiment[] = [];
|
private _experiments: IExperiment[] = [];
|
||||||
|
@ -127,7 +73,8 @@ export class ExperimentService extends Disposable implements IExperimentService
|
||||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||||
@IRequestService private readonly requestService: IRequestService,
|
@IRequestService private readonly requestService: IRequestService,
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
|
@IProductService private readonly productService: IProductService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -171,10 +118,10 @@ export class ExperimentService extends Disposable implements IExperimentService
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getExperiments(): Promise<IRawExperiment[]> {
|
protected getExperiments(): Promise<IRawExperiment[]> {
|
||||||
if (!product.experimentsUrl || this.configurationService.getValue('workbench.enableExperiments') === false) {
|
if (!this.productService.experimentsUrl || this.configurationService.getValue('workbench.enableExperiments') === false) {
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
return this.requestService.request({ type: 'GET', url: product.experimentsUrl }, CancellationToken.None).then(context => {
|
return this.requestService.request({ type: 'GET', url: this.productService.experimentsUrl }, CancellationToken.None).then(context => {
|
||||||
if (context.res.statusCode !== 200) {
|
if (context.res.statusCode !== 200) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||||
import { INotificationService, Severity, IPromptChoice } from 'vs/platform/notification/common/notification';
|
import { INotificationService, Severity, IPromptChoice } from 'vs/platform/notification/common/notification';
|
||||||
import { IExperimentService, IExperiment, ExperimentActionType, IExperimentActionPromptProperties, IExperimentActionPromptCommand, ExperimentState } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
import { IExperimentService, IExperiment, ExperimentActionType, IExperimentActionPromptProperties, IExperimentActionPromptCommand, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IExtensionsViewlet } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtensionsViewlet } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
import { IExperimentService, ExperimentService } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
|
import { ExperimentService } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { ExperimentService, ExperimentActionType, ExperimentState, IExperiment } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
import { ExperimentActionType, ExperimentState, IExperiment } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
|
import { ExperimentService } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
||||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
import { TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
||||||
|
@ -17,7 +18,7 @@ import { Emitter } from 'vs/base/common/event';
|
||||||
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test';
|
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test';
|
||||||
import { URLService } from 'vs/platform/url/common/urlService';
|
import { URLService } from 'vs/platform/url/common/urlService';
|
||||||
import { IURLService } from 'vs/platform/url/common/url';
|
import { IURLService } from 'vs/platform/url/common/url';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||||
|
@ -25,7 +26,6 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||||
import { assign } from 'vs/base/common/objects';
|
import { assign } from 'vs/base/common/objects';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||||
import { lastSessionDateStorageKey } from 'vs/platform/telemetry/node/workbenchCommonProperties';
|
|
||||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||||
import { ExperimentalPrompts } from 'vs/workbench/contrib/experiments/electron-browser/experimentalPrompt';
|
import { ExperimentalPrompts } from 'vs/workbench/contrib/experiments/electron-browser/experimentalPrompt';
|
||||||
import { ExperimentActionType, ExperimentState, IExperiment, IExperimentActionPromptProperties, IExperimentService, LocalizedPromptText } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
import { ExperimentActionType, ExperimentState, IExperiment, IExperimentActionPromptProperties, IExperimentService, LocalizedPromptText } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
|
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
|
||||||
import { TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
import { TestLifecycleService } from 'vs/workbench/test/workbenchTestServices';
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,10 @@ import { IExtensionManifest, IKeyBinding, IView, IViewContainer, ExtensionType }
|
||||||
import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||||
import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
|
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
||||||
import { EditorOptions } from 'vs/workbench/common/editor';
|
import { EditorOptions } from 'vs/workbench/common/editor';
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
|
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||||
|
@ -44,7 +43,7 @@ import { assign } from 'vs/base/common/objects';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { ExtensionsTree, ExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer';
|
import { ExtensionsTree, ExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer';
|
||||||
import { ShowCurrentReleaseNotesAction } from 'vs/workbench/contrib/update/electron-browser/update';
|
import { ShowCurrentReleaseNotesActionId } from 'vs/workbench/contrib/update/common/update';
|
||||||
import { KeybindingParser } from 'vs/base/common/keybindingParser';
|
import { KeybindingParser } from 'vs/base/common/keybindingParser';
|
||||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||||
|
@ -52,6 +51,7 @@ import { getDefaultValue } from 'vs/platform/configuration/common/configurationR
|
||||||
import { isUndefined } from 'vs/base/common/types';
|
import { isUndefined } from 'vs/base/common/types';
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { IWebviewService, Webview } from 'vs/workbench/contrib/webview/common/webview';
|
||||||
|
|
||||||
function renderBody(body: string): string {
|
function renderBody(body: string): string {
|
||||||
const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-resource://');
|
const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-resource://');
|
||||||
|
@ -194,8 +194,8 @@ export class ExtensionEditor extends BaseEditor {
|
||||||
@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService,
|
@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService,
|
||||||
@IStorageService storageService: IStorageService,
|
@IStorageService storageService: IStorageService,
|
||||||
@IExtensionService private readonly extensionService: IExtensionService,
|
@IExtensionService private readonly extensionService: IExtensionService,
|
||||||
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService
|
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
|
||||||
|
@IWebviewService private readonly webviewService: IWebviewService
|
||||||
) {
|
) {
|
||||||
super(ExtensionEditor.ID, telemetryService, themeService, storageService);
|
super(ExtensionEditor.ID, telemetryService, themeService, storageService);
|
||||||
this.extensionReadme = null;
|
this.extensionReadme = null;
|
||||||
|
@ -490,8 +490,8 @@ export class ExtensionEditor extends BaseEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
showFind(): void {
|
showFind(): void {
|
||||||
if (this.activeElement instanceof WebviewElement) {
|
if (this.activeElement && (<Webview>this.activeElement).showFind) {
|
||||||
this.activeElement.showFind();
|
(<Webview>this.activeElement).showFind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +537,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||||
.then(renderBody)
|
.then(renderBody)
|
||||||
.then(removeEmbeddedSVGs)
|
.then(removeEmbeddedSVGs)
|
||||||
.then(body => {
|
.then(body => {
|
||||||
const webviewElement = this.instantiationService.createInstance(WebviewElement,
|
const webviewElement = this.webviewService.createWebview('extensionEditor',
|
||||||
{
|
{
|
||||||
enableFindWidget: true,
|
enableFindWidget: true,
|
||||||
},
|
},
|
||||||
|
@ -558,7 +558,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Whitelist supported schemes for links
|
// Whitelist supported schemes for links
|
||||||
if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesAction.ID)) {
|
if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesActionId)) {
|
||||||
this.openerService.open(link);
|
this.openerService.open(link);
|
||||||
}
|
}
|
||||||
}, null, this.contentDisposables));
|
}, null, this.contentDisposables));
|
|
@ -13,9 +13,9 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
|
||||||
import { Event } from 'vs/base/common/event';
|
import { Event } from 'vs/base/common/event';
|
||||||
import { domEvent } from 'vs/base/browser/event';
|
import { domEvent } from 'vs/base/browser/event';
|
||||||
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
|
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
||||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||||
import { IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
|
@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
|
||||||
import { timeout, Delayer } from 'vs/base/common/async';
|
import { timeout, Delayer } from 'vs/base/common/async';
|
||||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { Event as EventOf, Emitter } from 'vs/base/common/event';
|
import { Event as EventOf, Emitter } from 'vs/base/common/event';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
|
@ -23,10 +23,10 @@ import {
|
||||||
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
|
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
|
||||||
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
||||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
|
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
|
||||||
} from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from './extensionsViews';
|
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||||
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
|
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
|
||||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||||
|
@ -339,7 +339,6 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
private extensionsBox: HTMLElement;
|
private extensionsBox: HTMLElement;
|
||||||
private primaryActions: IAction[];
|
private primaryActions: IAction[];
|
||||||
private secondaryActions: IAction[] | null;
|
private secondaryActions: IAction[] | null;
|
||||||
private disposables: IDisposable[] = [];
|
|
||||||
private readonly searchViewletState: MementoObject;
|
private readonly searchViewletState: MementoObject;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -374,14 +373,14 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
|
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
|
||||||
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
|
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
|
||||||
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
||||||
this.disposables.push(this.viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables));
|
this._register(this.viewletService.onDidViewletOpen(this.onViewletOpen, this));
|
||||||
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
|
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
|
||||||
|
|
||||||
this.extensionManagementService.getInstalled(ExtensionType.User).then(result => {
|
this.extensionManagementService.getInstalled(ExtensionType.User).then(result => {
|
||||||
this.hasInstalledExtensionsContextKey.set(result.length > 0);
|
this.hasInstalledExtensionsContextKey.set(result.length > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.configurationService.onDidChangeConfiguration(e => {
|
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectsConfiguration(AutoUpdateConfigurationKey)) {
|
if (e.affectsConfiguration(AutoUpdateConfigurationKey)) {
|
||||||
this.secondaryActions = null;
|
this.secondaryActions = null;
|
||||||
this.updateTitleArea();
|
this.updateTitleArea();
|
||||||
|
@ -389,7 +388,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) {
|
if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) {
|
||||||
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
||||||
}
|
}
|
||||||
}, this, this.disposables);
|
}, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
create(parent: HTMLElement): void {
|
create(parent: HTMLElement): void {
|
||||||
|
@ -401,7 +400,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
const placeholder = localize('searchExtensions', "Search Extensions in Marketplace");
|
const placeholder = localize('searchExtensions', "Search Extensions in Marketplace");
|
||||||
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : '';
|
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : '';
|
||||||
|
|
||||||
this.searchBox = this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
|
this.searchBox = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
|
||||||
triggerCharacters: ['@'],
|
triggerCharacters: ['@'],
|
||||||
sortKey: (item: string) => {
|
sortKey: (item: string) => {
|
||||||
if (item.indexOf(':') === -1) { return 'a'; }
|
if (item.indexOf(':') === -1) { return 'a'; }
|
||||||
|
@ -410,24 +409,22 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
else { return 'd'; }
|
else { return 'd'; }
|
||||||
},
|
},
|
||||||
provideResults: (query: string) => Query.suggestions(query)
|
provideResults: (query: string) => Query.suggestions(query)
|
||||||
}, placeholder, 'extensions:searchinput', { placeholderText: placeholder, value: searchValue });
|
}, placeholder, 'extensions:searchinput', { placeholderText: placeholder, value: searchValue }));
|
||||||
|
|
||||||
if (this.searchBox.getValue()) {
|
if (this.searchBox.getValue()) {
|
||||||
this.triggerSearch();
|
this.triggerSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.disposables.push(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
|
this._register(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
|
||||||
|
|
||||||
this.disposables.push(this.searchBox);
|
|
||||||
|
|
||||||
const _searchChange = new Emitter<string>();
|
const _searchChange = new Emitter<string>();
|
||||||
this.onSearchChange = _searchChange.event;
|
this.onSearchChange = _searchChange.event;
|
||||||
this.searchBox.onInputDidChange(() => {
|
this._register(this.searchBox.onInputDidChange(() => {
|
||||||
this.triggerSearch();
|
this.triggerSearch();
|
||||||
_searchChange.fire(this.searchBox.getValue());
|
_searchChange.fire(this.searchBox.getValue());
|
||||||
}, this, this.disposables);
|
}, this));
|
||||||
|
|
||||||
this.searchBox.onShouldFocusResults(() => this.focusListView(), this, this.disposables);
|
this._register(this.searchBox.onShouldFocusResults(() => this.focusListView(), this));
|
||||||
|
|
||||||
this._register(this.onDidChangeVisibility(visible => {
|
this._register(this.onDidChangeVisibility(visible => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
@ -614,52 +611,39 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||||
|
|
||||||
this.notificationService.error(err);
|
this.notificationService.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
this.disposables = dispose(this.disposables);
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StatusUpdater implements IWorkbenchContribution {
|
export class StatusUpdater extends Disposable implements IWorkbenchContribution {
|
||||||
|
|
||||||
private disposables: IDisposable[];
|
private readonly badgeHandle = this._register(new MutableDisposable());
|
||||||
private badgeHandle: IDisposable;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IActivityService private readonly activityService: IActivityService,
|
@IActivityService private readonly activityService: IActivityService,
|
||||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
|
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
|
||||||
) {
|
) {
|
||||||
extensionsWorkbenchService.onChange(this.onServiceChange, this, this.disposables);
|
super();
|
||||||
|
this._register(extensionsWorkbenchService.onChange(this.onServiceChange, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private onServiceChange(): void {
|
private onServiceChange(): void {
|
||||||
|
this.badgeHandle.clear();
|
||||||
dispose(this.badgeHandle);
|
|
||||||
|
|
||||||
if (this.extensionsWorkbenchService.local.some(e => e.state === ExtensionState.Installing)) {
|
if (this.extensionsWorkbenchService.local.some(e => e.state === ExtensionState.Installing)) {
|
||||||
this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge');
|
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) ? 1 : 0), 0);
|
const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) ? 1 : 0), 0);
|
||||||
if (outdated > 0) {
|
if (outdated > 0) {
|
||||||
const badge = new NumberBadge(outdated, n => localize('outdatedExtensions', '{0} Outdated Extensions', n));
|
const badge = new NumberBadge(outdated, n => localize('outdatedExtensions', '{0} Outdated Extensions', n));
|
||||||
this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge');
|
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
this.disposables = dispose(this.disposables);
|
|
||||||
dispose(this.badgeHandle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
||||||
|
|
||||||
private disposables: IDisposable[];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
|
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
|
||||||
@IWindowService private readonly windowService: IWindowService,
|
@IWindowService private readonly windowService: IWindowService,
|
||||||
|
@ -704,8 +688,4 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
||||||
}).then(() => undefined);
|
}).then(() => undefined);
|
||||||
}, err => this.logService.error(err));
|
}, err => this.logService.error(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
this.disposables = dispose(this.disposables);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { append, $, toggleClass } from 'vs/base/browser/dom';
|
import { append, $, toggleClass } from 'vs/base/browser/dom';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/electron-browser/extensionsList';
|
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/browser/extensionsList';
|
||||||
import { IExtension, IExtensionsWorkbenchService, ExtensionState } from '../common/extensions';
|
import { IExtension, IExtensionsWorkbenchService, ExtensionState } from '../common/extensions';
|
||||||
import { Query } from '../common/extensionQuery';
|
import { Query } from '../common/extensionQuery';
|
||||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||||
|
@ -27,14 +27,14 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||||
import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { WorkbenchPagedList } from 'vs/platform/list/browser/listService';
|
import { WorkbenchPagedList } from 'vs/platform/list/browser/listService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||||
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
|
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||||
import { distinct, coalesce } from 'vs/base/common/arrays';
|
import { distinct, coalesce } from 'vs/base/common/arrays';
|
||||||
import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
|
import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||||
import { alert } from 'vs/base/browser/ui/aria/aria';
|
import { alert } from 'vs/base/browser/ui/aria/aria';
|
||||||
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
|
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
|
||||||
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
|
@ -4,14 +4,14 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import 'vs/css!./media/extensionsWidgets';
|
import 'vs/css!./media/extensionsWidgets';
|
||||||
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState } from '../common/extensions';
|
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState } from '../common/extensions';
|
||||||
import { append, $, addClass } from 'vs/base/browser/dom';
|
import { append, $, addClass } from 'vs/base/browser/dom';
|
||||||
import * as platform from 'vs/base/common/platform';
|
import * as platform from 'vs/base/common/platform';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||||
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||||
|
@ -196,7 +196,7 @@ export class TooltipWidget extends ExtensionWidget {
|
||||||
export class RecommendationWidget extends ExtensionWidget {
|
export class RecommendationWidget extends ExtensionWidget {
|
||||||
|
|
||||||
private element?: HTMLElement;
|
private element?: HTMLElement;
|
||||||
private disposables: IDisposable[] = [];
|
private readonly disposables = this._register(new DisposableStore());
|
||||||
|
|
||||||
private _tooltip: string;
|
private _tooltip: string;
|
||||||
get tooltip(): string { return this._tooltip; }
|
get tooltip(): string { return this._tooltip; }
|
||||||
|
@ -227,7 +227,7 @@ export class RecommendationWidget extends ExtensionWidget {
|
||||||
this.parent.removeChild(this.element);
|
this.parent.removeChild(this.element);
|
||||||
}
|
}
|
||||||
this.element = undefined;
|
this.element = undefined;
|
||||||
this.disposables = dispose(this.disposables);
|
this.disposables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): void {
|
render(): void {
|
||||||
|
@ -256,8 +256,7 @@ export class RecommendationWidget extends ExtensionWidget {
|
||||||
|
|
||||||
export class RemoteBadgeWidget extends ExtensionWidget {
|
export class RemoteBadgeWidget extends ExtensionWidget {
|
||||||
|
|
||||||
private remoteBadge: RemoteBadge | null;
|
private readonly remoteBadge = this._register(new MutableDisposable<RemoteBadge>());
|
||||||
private disposables: IDisposable[] = [];
|
|
||||||
|
|
||||||
private element: HTMLElement;
|
private element: HTMLElement;
|
||||||
|
|
||||||
|
@ -274,12 +273,10 @@ export class RemoteBadgeWidget extends ExtensionWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
private clear(): void {
|
private clear(): void {
|
||||||
if (this.remoteBadge) {
|
if (this.remoteBadge.value) {
|
||||||
this.element.removeChild(this.remoteBadge.element);
|
this.element.removeChild(this.remoteBadge.value.element);
|
||||||
this.remoteBadge.dispose();
|
|
||||||
}
|
}
|
||||||
this.remoteBadge = null;
|
this.remoteBadge.clear();
|
||||||
this.disposables = dispose(this.disposables);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): void {
|
render(): void {
|
||||||
|
@ -288,17 +285,10 @@ export class RemoteBadgeWidget extends ExtensionWidget {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||||
this.remoteBadge = this.instantiationService.createInstance(RemoteBadge, this.tooltip);
|
this.remoteBadge.value = this.instantiationService.createInstance(RemoteBadge, this.tooltip);
|
||||||
append(this.element, this.remoteBadge.element);
|
append(this.element, this.remoteBadge.value.element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
if (this.remoteBadge) {
|
|
||||||
this.remoteBadge.dispose();
|
|
||||||
}
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RemoteBadge extends Disposable {
|
class RemoteBadge extends Disposable {
|
Before Width: | Height: | Size: 484 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 474 B |
Before Width: | Height: | Size: 419 B After Width: | Height: | Size: 419 B |
Before Width: | Height: | Size: 484 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |