Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)

This commit is contained in:
Anthony Dresser
2019-04-14 22:29:14 -07:00
committed by GitHub
parent 6dbf757385
commit 57242a2e13
210 changed files with 4898 additions and 3018 deletions

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -e
yarn gulp vscode-darwin-min
yarn gulp upload-vscode-sourcemaps

View File

@@ -18,9 +18,15 @@ steps:
password $(VSCODE_MIXIN_PASSWORD) password $(VSCODE_MIXIN_PASSWORD)
EOF EOF
git config user.email "vscode@microsoft.com"
git config user.name "VSCode"
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
git fetch distro
git merge $(node -p "require('./package.json').distro")
yarn yarn
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin yarn gulp mixin
yarn gulp -- hygiene yarn gulp hygiene
yarn monaco-compile-check yarn monaco-compile-check
node build/azure-pipelines/common/installDistro.js node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js node build/lib/builtInExtensions.js
@@ -30,10 +36,7 @@ steps:
set -e set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \ VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- vscode-darwin-min ./build/azure-pipelines/darwin/build.sh
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- upload-vscode-sourcemaps
displayName: Build displayName: Build
- script: | - script: |
@@ -43,6 +46,11 @@ steps:
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME" # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
displayName: Run unit tests displayName: Run unit tests
- script: |
set -e
./scripts/test-integration.sh --build --tfs "Integration Tests"
displayName: Run integration tests
- script: | - script: |
set -e set -e
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd
@@ -69,30 +77,12 @@ steps:
- script: | - script: |
set -e set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
# remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg"
# publish the build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/azure-pipelines/common/publish.js \
"$(VSCODE_QUALITY)" \
darwin \
archive \
"VSCode-darwin-$(VSCODE_QUALITY).zip" \
$VERSION \
true \
../VSCode-darwin.zip
# publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)"
# upload configuration
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \ AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- upload-vscode-configuration AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
./build/azure-pipelines/darwin/publish.sh
displayName: Publish displayName: Publish
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg"
# publish the build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
node build/azure-pipelines/common/publish.js \
"$VSCODE_QUALITY" \
darwin \
archive \
"VSCode-darwin-$VSCODE_QUALITY.zip" \
$VERSION \
true \
../VSCode-darwin.zip
# publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS"
# upload configuration
yarn gulp upload-vscode-configuration

View File

@@ -24,6 +24,7 @@ steps:
git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git" git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git"
git fetch distro git fetch distro
git push distro origin/master:refs/heads/master
git merge $(node -p "require('./package.json').distro") git merge $(node -p "require('./package.json').distro")
displayName: Merge Distro displayName: Sync & Merge Distro

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e
yarn gulp "vscode-linux-$VSCODE_ARCH-min"

View File

@@ -22,87 +22,45 @@ steps:
password $(VSCODE_MIXIN_PASSWORD) password $(VSCODE_MIXIN_PASSWORD)
EOF EOF
git config user.email "vscode@microsoft.com"
git config user.name "VSCode"
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
git fetch distro
git merge $(node -p "require('./package.json').distro")
CHILD_CONCURRENCY=1 yarn CHILD_CONCURRENCY=1 yarn
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin yarn gulp mixin
npm run gulp -- hygiene yarn gulp hygiene
npm run monaco-compile-check yarn monaco-compile-check
node build/azure-pipelines/common/installDistro.js node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js node build/lib/builtInExtensions.js
displayName: Prepare build
- script: | - script: |
set -e set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
name: build ./build/azure-pipelines/linux/build.sh
displayName: Build
- script: | - script: |
set -e set -e
npm run gulp -- "electron-$(VSCODE_ARCH)" yarn gulp "electron-$(VSCODE_ARCH)"
# 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-$(VSCODE_ARCH)"
name: test displayName: Run unit tests
- script: | - script: |
set -e set -e
REPO="$(pwd)"
ROOT="$REPO/.."
ARCH="$(VSCODE_ARCH)"
# Publish tarball
PLATFORM_LINUX="linux-$(VSCODE_ARCH)"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(date +%s)"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \ AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH" VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
# Publish hockeyapp symbols ./build/azure-pipelines/linux/publish.sh
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)" displayName: Publish
# Publish DEB
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
PLATFORM_DEB="linux-deb-$ARCH"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
# Publish RPM
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
PLATFORM_RPM="linux-rpm-$ARCH"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
# Publish Snap
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz"
rm -rf $SNAP_TARBALL_PATH
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection' displayName: 'Component Detection'

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -e
REPO="$(pwd)"
ROOT="$REPO/.."
# Publish tarball
PLATFORM_LINUX="linux-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(date +%s)"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
# Publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64"
# Publish DEB
yarn gulp "vscode-linux-$VSCODE_ARCH-build-deb"
PLATFORM_DEB="linux-deb-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
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"
# Publish RPM
yarn gulp "vscode-linux-$VSCODE_ARCH-build-rpm"
PLATFORM_RPM="linux-rpm-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
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"
# Publish Snap
yarn gulp "vscode-linux-$VSCODE_ARCH-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz"
rm -rf $SNAP_TARBALL_PATH
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)

View File

@@ -0,0 +1,4 @@
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min" }
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" }

View File

@@ -18,34 +18,47 @@ steps:
"machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII "machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)" $env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1" $env:CHILD_CONCURRENCY="1"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { git config user.email "vscode@microsoft.com" }
exec { git config user.name "VSCode" }
exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" }
exec { git fetch distro }
exec { git merge $(node -p "require('./package.json').distro") }
exec { yarn } exec { yarn }
exec { npm run gulp -- mixin } exec { yarn gulp mixin }
exec { npm run gulp -- hygiene } exec { yarn gulp hygiene }
exec { npm run monaco-compile-check } exec { yarn monaco-compile-check }
exec { node build/azure-pipelines/common/installDistro.js } exec { node build/azure-pipelines/common/installDistro.js }
exec { node build/lib/builtInExtensions.js } exec { node build/lib/builtInExtensions.js }
displayName: Prepare build
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" } .\build\azure-pipelines\win32\build.ps1
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-inno-updater" } displayName: Build
name: build
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
exec { npm run gulp -- "electron-$(VSCODE_ARCH)" } exec { yarn gulp "electron-$(VSCODE_ARCH)" }
exec { .\scripts\test.bat --build --tfs "Unit Tests" } exec { .\scripts\test.bat --build --tfs "Unit Tests" }
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)" # yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
name: test displayName: Run unit tests
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { yarn gulp "electron-$(VSCODE_ARCH)" }
exec { .\scripts\test-integration.bat --build --tfs "Integration Tests" }
displayName: Run integration tests
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs: inputs:
ConnectedServiceName: 'ESRP CodeSign' ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)' FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)'
Pattern: '*.dll,*.exe,*.node' Pattern: '*.dll,*.exe,*.node'
signConfigType: inlineSignParams signConfigType: inlineSignParams
inlineOperation: | inlineOperation: |
@@ -119,31 +132,11 @@ steps:
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-system-setup" "vscode-win32-$(VSCODE_ARCH)-user-setup" --sign }
$Repo = "$(pwd)"
$Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)" $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)" $env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$env:VSCODE_HOCKEYAPP_TOKEN = "$(VSCODE_HOCKEYAPP_TOKEN)"
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" } .\build\azure-pipelines\win32\publish.ps1
displayName: Publish
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-user" setup "VSCodeUserSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $UserExe }
# publish hockeyapp symbols
$hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" }
exec { node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId }
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection' displayName: 'Component Detection'

View File

@@ -0,0 +1,28 @@
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$Arch = "$env:VSCODE_ARCH"
exec { yarn gulp "vscode-win32-$Arch-archive" "vscode-win32-$Arch-system-setup" "vscode-win32-$Arch-user-setup" --sign }
$Repo = "$(pwd)"
$Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip"
$Build = "$Root\VSCode-win32-$Arch"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$AssetPlatform = if ("$Arch" -eq "ia32") { "win32" } else { "win32-x64" }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe }
# publish hockeyapp symbols
$hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" }
exec { node build/azure-pipelines/common/symbols.js "$env:VSCODE_MIXIN_PASSWORD" "$env:VSCODE_HOCKEYAPP_TOKEN" "$Arch" $hockeyAppId }

View File

@@ -75,9 +75,10 @@ const vscodeResources = [
'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,cur,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',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**', 'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/contrib/debug/**/*.json', 'out-build/vs/workbench/contrib/debug/**/*.json',
@@ -431,6 +432,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(replace('@@VERSION@@', version)) .pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit)) .pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(replace('@@QUALITY@@', quality))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; }))); .pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' }) result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })

View File

@@ -237,6 +237,7 @@ exports.fromMarketplace = fromMarketplace;
const excludedExtensions = [ const excludedExtensions = [
'vscode-api-tests', 'vscode-api-tests',
'vscode-colorize-tests', 'vscode-colorize-tests',
'vscode-test-resolver',
'ms-vscode.node-debug', 'ms-vscode.node-debug',
'ms-vscode.node-debug2', 'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}

View File

@@ -283,6 +283,7 @@ interface IPackageExtensionsOptions {
const excludedExtensions = [ const excludedExtensions = [
'vscode-api-tests', 'vscode-api-tests',
'vscode-colorize-tests', 'vscode-colorize-tests',
'vscode-test-resolver',
'ms-vscode.node-debug', 'ms-vscode.node-debug',
'ms-vscode.node-debug2', 'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}

View File

@@ -111,11 +111,11 @@
"git": { "git": {
"name": "vscode-octicons-font", "name": "vscode-octicons-font",
"repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font", "repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font",
"commitHash": "5095860bb929919670646e2dfa0ee47d9b93bcb9" "commitHash": "4f69de3a233ed501c2098e33047e116ac2fbbf42"
} }
}, },
"license": "MIT", "license": "MIT",
"version": "1.0.0" "version": "1.1.0"
}, },
{ {
"component": { "component": {

View File

@@ -1031,7 +1031,7 @@
], ],
"markdownDescription": "%config.path%", "markdownDescription": "%config.path%",
"default": null, "default": null,
"scope": "application" "scope": "machine"
}, },
"git.autoRepositoryDetection": { "git.autoRepositoryDetection": {
"type": [ "type": [

View File

@@ -381,7 +381,14 @@ export class MarkdownPreview extends Disposable {
clearTimeout(this.throttleTimer); clearTimeout(this.throttleTimer);
this.throttleTimer = undefined; this.throttleTimer = undefined;
const document = await vscode.workspace.openTextDocument(resource); let document: vscode.TextDocument;
try {
document = await vscode.workspace.openTextDocument(resource);
} catch {
await this.showFileNotFoundError();
return;
}
if (!this.forceUpdate && this.currentVersion && this.currentVersion.resource.fsPath === resource.fsPath && this.currentVersion.version === document.version) { if (!this.forceUpdate && this.currentVersion && this.currentVersion.resource.fsPath === resource.fsPath && this.currentVersion.version === document.version) {
if (this.line) { if (this.line) {
this.updateForView(resource, this.line); this.updateForView(resource, this.line);
@@ -391,12 +398,9 @@ export class MarkdownPreview extends Disposable {
this.forceUpdate = false; this.forceUpdate = false;
this.currentVersion = { resource, version: document.version }; this.currentVersion = { resource, version: document.version };
const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state);
if (this._resource === resource) { if (this._resource === resource) {
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked); const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state);
this.editor.iconPath = this.iconPath; this.setContent(content);
this.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, this._contributionProvider.contributions);
this.editor.webview.html = content;
} }
} }
@@ -456,7 +460,22 @@ export class MarkdownPreview extends Disposable {
} }
} }
vscode.workspace.openTextDocument(this._resource).then(vscode.window.showTextDocument); vscode.workspace.openTextDocument(this._resource)
.then(vscode.window.showTextDocument)
.then(undefined, () => {
vscode.window.showErrorMessage(localize('preview.clickOpenFailed', 'Could not open {0}', this._resource.toString()));
});
}
private async showFileNotFoundError() {
this.setContent(this._contentProvider.provideFileNotFoundContent(this._resource));
}
private setContent(html: string): void {
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
this.editor.iconPath = this.iconPath;
this.editor.webview.options = MarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions);
this.editor.webview.html = html;
} }
private async onDidClickPreviewLink(path: string, fragment: string | undefined) { private async onDidClickPreviewLink(path: string, fragment: string | undefined) {

View File

@@ -90,6 +90,19 @@ export class MarkdownContentProvider {
</html>`; </html>`;
} }
public provideFileNotFoundContent(
resource: vscode.Uri,
): string {
const resourcePath = path.basename(resource.fsPath);
const body = localize('preview.notFound', '{0} cannot be found', resourcePath);
return `<!DOCTYPE html>
<html>
<body class="vscode-body">
${body}
</body>
</html>`;
}
private extensionResourcePath(mediaFile: string): string { private extensionResourcePath(mediaFile: string): string {
return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))) return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile)))
.with({ scheme: 'vscode-resource' }) .with({ scheme: 'vscode-resource' })

View File

@@ -3,7 +3,7 @@
"version": "0.0.1", "version": "0.0.1",
"description": "Dependencies shared by all extensions", "description": "Dependencies shared by all extensions",
"dependencies": { "dependencies": {
"typescript": "3.4.3-insiders.20190408" "typescript": "3.4.3"
}, },
"scripts": { "scripts": {
"postinstall": "node ./postinstall" "postinstall": "node ./postinstall"

View File

@@ -68,7 +68,12 @@
}, },
{ {
"name": "Control flow keywords", "name": "Control flow keywords",
"scope": "keyword.control", "scope": [
"keyword.control",
"keyword.operator.new.cpp",
"keyword.operator.delete.cpp",
"keyword.other.using"
],
"settings": { "settings": {
"foreground": "#C586C0" "foreground": "#C586C0"
} }

View File

@@ -65,7 +65,12 @@
}, },
{ {
"name": "Control flow keywords", "name": "Control flow keywords",
"scope": "keyword.control", "scope": [
"keyword.control",
"keyword.operator.new.cpp",
"keyword.operator.delete.cpp",
"keyword.other.using"
],
"settings": { "settings": {
"foreground": "#C586C0" "foreground": "#C586C0"
} }

View File

@@ -68,7 +68,12 @@
}, },
{ {
"name": "Control flow keywords", "name": "Control flow keywords",
"scope": "keyword.control", "scope": [
"keyword.control",
"keyword.operator.new.cpp",
"keyword.operator.delete.cpp",
"keyword.other.using"
],
"settings": { "settings": {
"foreground": "#AF00DB" "foreground": "#AF00DB"
} }

View File

@@ -113,7 +113,10 @@
"name": "Keywords", "name": "Keywords",
"scope": [ "scope": [
"keyword", "keyword",
"keyword.control" "keyword.control",
"keyword.operator.new.cpp",
"keyword.operator.delete.cpp",
"keyword.other.using"
], ],
"settings": { "settings": {
"foreground": "#98676a" "foreground": "#98676a"

View File

@@ -255,7 +255,12 @@
}, },
{ {
"name": "Keyword Control", "name": "Keyword Control",
"scope": "keyword.control", "scope": [
"keyword.control",
"keyword.operator.new.cpp",
"keyword.operator.delete.cpp",
"keyword.other.using"
],
"settings": { "settings": {
"fontStyle": "", "fontStyle": "",
"foreground": "#9872A2" "foreground": "#9872A2"

View File

@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import API from '../utils/api';
import { VersionDependentRegistration } from '../utils/dependentRegistration';
import * as typeConverters from '../utils/typeConverters';
class SmartSelection implements vscode.SelectionRangeProvider {
public static readonly minVersion = API.v350;
public constructor(
private readonly client: ITypeScriptServiceClient
) { }
public async provideSelectionRanges(
document: vscode.TextDocument,
positions: vscode.Position[],
token: vscode.CancellationToken,
): Promise<vscode.SelectionRange[] | undefined> {
const file = this.client.toOpenedFilePath(document);
if (!file) {
return undefined;
}
const args: Proto.FileRequestArgs & { locations: Proto.Location[] } = {
file,
locations: positions.map(typeConverters.Position.toLocation)
};
const response = await this.client.execute('selectionRange', args, token);
if (response.type !== 'response' || !response.body) {
return undefined;
}
return response.body.map(SmartSelection.convertSelectionRange);
}
private static convertSelectionRange(
selectionRange: Proto.SelectionRange
): vscode.SelectionRange {
return new vscode.SelectionRange(
typeConverters.Range.fromTextSpan(selectionRange.textSpan),
selectionRange.parent ? SmartSelection.convertSelectionRange(selectionRange.parent) : undefined,
);
}
}
export function register(
selector: vscode.DocumentSelector,
client: ITypeScriptServiceClient,
) {
return new VersionDependentRegistration(client, SmartSelection.minVersion, () =>
vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client)));
}

View File

@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import 'mocha';
import * as vscode from 'vscode';
import { CURSOR, withRandomFileEditor } from './testUtils';
const onDocumentChange = (doc: vscode.TextDocument): Promise<vscode.TextDocument> => {
return new Promise<vscode.TextDocument>(resolve => {
const sub = vscode.workspace.onDidChangeTextDocument(e => {
if (e.document !== doc) {
return;
}
sub.dispose();
resolve(e.document);
});
});
};
const type = async (document: vscode.TextDocument, text: string): Promise<vscode.TextDocument> => {
const onChange = onDocumentChange(document);
await vscode.commands.executeCommand('type', { text });
await onChange;
return document;
};
suite('OnEnter', () => {
test('should indent after if block with braces', () => {
return withRandomFileEditor(`if (true) {${CURSOR}`, 'js', async (_editor, document) => {
await type(document, '\nx');
assert.strictEqual(document.getText(), `if (true) {\n x`);
});
});
test('should indent within empty object literal', () => {
return withRandomFileEditor(`({${CURSOR}})`, 'js', async (_editor, document) => {
await type(document, '\nx');
assert.strictEqual(document.getText(), `({\n x\n})`);
});
});
test('should indent after simple jsx tag with attributes', () => {
return withRandomFileEditor(`const a = <div onclick={bla}>${CURSOR}`, 'jsx', async (_editor, document) => {
await type(document, '\nx');
assert.strictEqual(document.getText(), `const a = <div onclick={bla}>\n x`);
});
});
test('should indent after simple jsx tag with attributes', () => {
return withRandomFileEditor(`const a = <div onclick={bla}>${CURSOR}`, 'jsx', async (_editor, document) => {
await type(document, '\nx');
assert.strictEqual(document.getText(), `const a = <div onclick={bla}>\n x`);
});
});
});

View File

@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as os from 'os';
import { join } from 'path';
function rndName() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
}
export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable<vscode.Uri> {
return new Promise((resolve, reject) => {
const tmpFile = join(os.tmpdir(), rndName() + '.' + fileExtension);
fs.writeFile(tmpFile, contents, (error) => {
if (error) {
return reject(error);
}
resolve(vscode.Uri.file(tmpFile));
});
});
}
export function deleteFile(file: vscode.Uri): Thenable<boolean> {
return new Promise((resolve, reject) => {
fs.unlink(file.fsPath, (err) => {
if (err) {
reject(err);
} else {
resolve(true);
}
});
});
}
export const CURSOR = '$$CURSOR$$';
export function withRandomFileEditor(
contents: string,
fileExtension: string,
run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Thenable<void>
): Thenable<boolean> {
const cursorIndex = contents.indexOf(CURSOR);
return createRandomFile(contents.replace(CURSOR, ''), fileExtension).then(file => {
return vscode.workspace.openTextDocument(file).then(doc => {
return vscode.window.showTextDocument(doc).then((editor) => {
if (cursorIndex >= 0) {
const pos = doc.positionAt(cursorIndex);
editor.selection = new vscode.Selection(pos, pos);
}
return run(editor, doc).then(_ => {
if (doc.isDirty) {
return doc.save().then(() => {
return deleteFile(file);
});
} else {
return deleteFile(file);
}
});
});
});
});
}

View File

@@ -2,7 +2,7 @@
# yarn lockfile v1 # yarn lockfile v1
typescript@3.4.3-insiders.20190408: typescript@3.4.3:
version "3.4.3-insiders.20190408" version "3.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.3-insiders.20190408.tgz#18d98336c693a13dc8b2d5f39b70268c018c650b" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.3.tgz#0eb320e4ace9b10eadf5bc6103286b0f8b7c224f"
integrity sha512-5SI6EA+2u0ea/Uy0qCEczh8vBR0ByVaCFCyU0RdROROw8V5O4OIQHMFcnIdyg+nnfRGYp39PxvllGMDpsTFOOQ== integrity sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ==

View File

@@ -75,7 +75,7 @@
"vscode-ripgrep": "^1.2.5", "vscode-ripgrep": "^1.2.5",
"vscode-sqlite3": "4.0.7", "vscode-sqlite3": "4.0.7",
"vscode-textmate": "^4.0.1", "vscode-textmate": "^4.0.1",
"vscode-xterm": "3.13.0-beta2", "vscode-xterm": "3.13.0-beta3",
"yauzl": "^2.9.1", "yauzl": "^2.9.1",
"yazl": "^2.4.3", "yazl": "^2.4.3",
"zone.js": "^0.8.4" "zone.js": "^0.8.4"
@@ -119,6 +119,7 @@
"gulp-eslint": "^5.0.0", "gulp-eslint": "^5.0.0",
"gulp-filter": "^5.1.0", "gulp-filter": "^5.1.0",
"gulp-flatmap": "^1.0.2", "gulp-flatmap": "^1.0.2",
"gulp-gunzip": "^1.0.0",
"gulp-json-editor": "^2.5.0", "gulp-json-editor": "^2.5.0",
"gulp-plumber": "^1.2.0", "gulp-plumber": "^1.2.0",
"gulp-remote-src": "^0.4.4", "gulp-remote-src": "^0.4.4",
@@ -128,6 +129,7 @@
"gulp-tsb": "2.0.7", "gulp-tsb": "2.0.7",
"gulp-tslint": "^8.1.3", "gulp-tslint": "^8.1.3",
"gulp-uglify": "^3.0.0", "gulp-uglify": "^3.0.0",
"gulp-untar": "^0.0.7",
"gulp-vinyl-zip": "^2.1.2", "gulp-vinyl-zip": "^2.1.2",
"husky": "^0.13.1", "husky": "^0.13.1",
"innosetup-compiler": "^5.5.60", "innosetup-compiler": "^5.5.60",
@@ -177,8 +179,8 @@
"url": "https://github.com/Microsoft/azuredatastudio/issues" "url": "https://github.com/Microsoft/azuredatastudio/issues"
}, },
"optionalDependencies": { "optionalDependencies": {
"vscode-windows-registry": "1.0.1",
"vscode-windows-ca-certs": "0.1.0", "vscode-windows-ca-certs": "0.1.0",
"vscode-windows-registry": "1.0.1",
"windows-foreground-love": "0.1.0", "windows-foreground-love": "0.1.0",
"windows-mutex": "0.2.1", "windows-mutex": "0.2.1",
"windows-process-tree": "0.2.3" "windows-process-tree": "0.2.3"
@@ -189,4 +191,4 @@
"natives": "1.1.6", "natives": "1.1.6",
"@types/node": "10.12.12" "@types/node": "10.12.12"
} }
} }

View File

@@ -3,6 +3,15 @@
# Copyright (c) Microsoft Corporation. All rights reserved. # Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Source EULA. See License.txt in the project root for license information. # Licensed under the Source EULA. See License.txt in the project root for license information.
# test that VSCode wasn't installed inside WSL
if grep -qi Microsoft /proc/version; then
echo "To use VS Code with the Windows Subsystem for Linux, please install VS Code in Windows and uninstall the Linux version in WSL. You can then use the '@@PRODNAME@@' command in a WSL terminal just as you would in a normal command prompt." 1>&2
read -e -p "Do you want to continue anyways ? [y/N] " YN
[[ $YN == "n" || $YN == "N" || $YN == "" ]] && exit 1
fi
# If root, ensure that --user-data-dir or --file-write is specified # If root, ensure that --user-data-dir or --file-write is specified
if [ "$(id -u)" = "0" ]; then if [ "$(id -u)" = "0" ]; then
for i in $@ for i in $@

View File

@@ -2,28 +2,31 @@
# #
# Copyright (c) Microsoft Corporation. All rights reserved. # Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Source EULA. See License.txt in the project root for license information. # Licensed under the Source EULA. See License.txt in the project root for license information.
COMMIT="@@COMMIT@@"
APP_NAME="@@APPNAME@@"
QUALITY="@@QUALITY@@"
NAME="@@NAME@@" set -e
VSCODE_PATH="$(dirname "$(dirname "$(realpath "$0")")")"
ELECTRON="$VSCODE_PATH/$NAME.exe" if grep -qi Microsoft /proc/version; then
if grep -q Microsoft /proc/version; then # in a wsl shell
if [ -x /bin/wslpath ]; then WIN_CODE_CMD=$(wslpath -w "$(dirname "$(realpath "$0")")/$APP_NAME.cmd")
# On recent WSL builds, we just need to set WSLENV so that
# ELECTRON_RUN_AS_NODE is visible to the win32 process WSL_EXT_ID="ms-vscode.remote-wsl"
export WSLENV=ELECTRON_RUN_AS_NODE/w:$WSLENV WSL_EXT_WLOC=$(cmd.exe /c "$WIN_CODE_CMD" --locate-extension $WSL_EXT_ID)
CLI=$(wslpath -m "$VSCODE_PATH/resources/app/out/cli.js") if ! [ -z "$WSL_EXT_WLOC" ]; then
else # replace \r\n with \n in WSL_EXT_WLOC, get linux path for
# If running under older WSL, don't pass cli.js to Electron as WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode.sh
# environment vars cannot be transferred from WSL to Windows $WSL_CODE $COMMIT $QUALITY "$WIN_CODE_CMD" "$APP_NAME" "$@"
# See: https://github.com/Microsoft/BashOnWindows/issues/1363
# https://github.com/Microsoft/BashOnWindows/issues/1494
"$ELECTRON" "$@"
exit $? exit $?
fi fi
elif [ "$(expr substr $(uname -s) 1 9)" == "CYGWIN_NT" ]; then fi
if [ -x "$(command -v cygpath)" ]; then
CLI=$(cygpath -m "$VSCODE_PATH/resources/app/out/cli.js") CLI=$(cygpath -m "$VSCODE_PATH/resources/app/out/cli.js")
else else
CLI="$VSCODE_PATH/resources/app/out/cli.js" CLI="$VSCODE_PATH/resources/app/out/cli.js"
fi fi
ELECTRON="$VSCODE_PATH/$NAME.exe"
ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"
exit $? exit $?

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; } realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname "$(dirname "$(realpath "$0")")") ROOT=$(dirname "$(dirname "$(realpath "$0")")")
@@ -9,6 +11,9 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
export ELECTRON_ENABLE_LOGGING=1 export ELECTRON_ENABLE_LOGGING=1
else else
ROOT=$(dirname "$(dirname "$(readlink -f $0)")") ROOT=$(dirname "$(dirname "$(readlink -f $0)")")
if grep -qi Microsoft /proc/version; then
IN_WSL=true
fi
fi fi
function code() { function code() {
@@ -50,4 +55,23 @@ function code() {
exec "$CODE" . "$@" exec "$CODE" . "$@"
} }
code "$@" function code-wsl()
{
# in a wsl shell
local WIN_CODE_CLI_CMD=$(wslpath -w "$ROOT/scripts/code-cli.bat")
local WSL_EXT_ID="ms-vscode.remote-wsl"
local WSL_EXT_WLOC=$(cmd.exe /c "$WIN_CODE_CLI_CMD" --locate-extension $WSL_EXT_ID)
if ! [ -z "$WSL_EXT_WLOC" ]; then
# replace \r\n with \n in WSL_EXT_WLOC
local WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode-dev.sh
$WSL_CODE "$ROOT" "$@"
exit $?
fi
}
if [ -z ${IN_WSL+x} ]; then
code "$@"
else
code-wsl "$@"
fi

View File

@@ -11,6 +11,10 @@ const bootstrap = require('./bootstrap');
// Enable ASAR in our forked processes // Enable ASAR in our forked processes
bootstrap.enableASARSupport(); bootstrap.enableASARSupport();
if (process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']) {
bootstrap.injectNodeModuleLookupPath(process.env['VSCODE_INJECT_NODE_MODULE_LOOKUP_PATH']);
}
// Configure: pipe logging to parent process // Configure: pipe logging to parent process
if (!!process.send && process.env.PIPE_LOGGING === 'true') { if (!!process.send && process.env.PIPE_LOGGING === 'true') {
pipeLoggingToParent(); pipeLoggingToParent();

32
src/bootstrap.js vendored
View File

@@ -20,6 +20,38 @@ process.on('SIGPIPE', () => {
//#endregion //#endregion
//#region Add support for redirecting the loading of node modules
exports.injectNodeModuleLookupPath = function (injectPath) {
if (!injectPath) {
throw new Error('Missing injectPath');
}
// @ts-ignore
const Module = require('module');
const path = require('path');
const nodeModulesPath = path.join(__dirname, '../node_modules');
// @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore
Module._resolveLookupPaths = function (moduleName, parent, newReturn) {
const result = originalResolveLookupPaths(moduleName, parent, newReturn);
const paths = newReturn ? result : result[1];
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === nodeModulesPath) {
paths.splice(i, 0, injectPath);
break;
}
}
return result;
};
};
//#endregion
//#region Add support for using node_modules.asar //#region Add support for using node_modules.asar
/** /**
* @param {string=} nodeModulesPath * @param {string=} nodeModulesPath

View File

@@ -41,6 +41,7 @@ import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration'; import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { ISchemeTransformer } from 'vs/workbench/api/common/extHostLanguageFeatures';
export interface ISqlExtensionApiFactory { export interface ISqlExtensionApiFactory {
vsCodeFactory(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; vsCodeFactory(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -58,9 +59,11 @@ export function createApiFactory(
extHostConfiguration: ExtHostConfiguration, extHostConfiguration: ExtHostConfiguration,
extensionService: ExtHostExtensionService, extensionService: ExtHostExtensionService,
logService: ExtHostLogService, logService: ExtHostLogService,
extHostStorage: ExtHostStorage extHostStorage: ExtHostStorage,
schemeTransformer: ISchemeTransformer | null,
outputChannelName: string
): ISqlExtensionApiFactory { ): ISqlExtensionApiFactory {
let vsCodeFactory = extHostApi.createApiFactory(initData, rpcProtocol, extHostWorkspace, extHostConfiguration, extensionService, logService, extHostStorage); let vsCodeFactory = extHostApi.createApiFactory(initData, rpcProtocol, extHostWorkspace, extHostConfiguration, extensionService, logService, extHostStorage, schemeTransformer, outputChannelName);
// Addressable instances // Addressable instances
const extHostAccountManagement = rpcProtocol.set(SqlExtHostContext.ExtHostAccountManagement, new ExtHostAccountManagement(rpcProtocol)); const extHostAccountManagement = rpcProtocol.set(SqlExtHostContext.ExtHostAccountManagement, new ExtHostAccountManagement(rpcProtocol));

View File

@@ -1,42 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ITelemetryService, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
const fs = require('fs');
/**
* Write telemetry into a file for test purposes
*/
export class FileTelemetryService implements ITelemetryService {
_serviceBrand: undefined;
private _isFirst = true;
constructor(private _outputFile: string) {
}
publicLog(eventName: string, data?: ITelemetryData) {
let telemetryData = JSON.stringify(Object.assign({ eventName: eventName, data: data }));
if (this._outputFile) {
if (this._isFirst) {
fs.open(this._outputFile, fs.O_WRONLY | fs.O_CREAT, (err, fr) => {
fs.writeFileSync(this._outputFile, telemetryData + '\n');
this._isFirst = false;
});
} else {
fs.appendFileSync(this._outputFile, telemetryData + '\n');
}
}
return Promise.resolve<void>(null);
}
isOptedIn: true;
getTelemetryInfo(): Promise<ITelemetryInfo> {
return Promise.resolve({
instanceId: 'someValue.instanceId',
sessionId: 'someValue.sessionId',
machineId: 'someValue.machineId'
});
}
}

View File

@@ -7,6 +7,9 @@ import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/t
// Test stubs for commonly used objects // Test stubs for commonly used objects
export class TelemetryServiceStub implements ITelemetryService { export class TelemetryServiceStub implements ITelemetryService {
setEnabled(value: boolean): void {
// no op;
}
_serviceBrand: any; _serviceBrand: any;
@@ -23,4 +26,4 @@ export class TelemetryServiceStub implements ITelemetryService {
} }
isOptedIn: boolean; isOptedIn: boolean;
} }

View File

@@ -1,18 +1,16 @@
{ {
"extends": "./tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"noEmit": true, "noEmit": true,
"types": [],
"paths": {},
"module": "amd", "module": "amd",
"moduleResolution": "classic", "moduleResolution": "classic",
"noImplicitAny": false,
"removeComments": false, "removeComments": false,
"preserveConstEnums": true, "preserveConstEnums": true,
"target": "es5", "target": "es5",
"sourceMap": false, "sourceMap": false,
"experimentalDecorators": true,
"declaration": true, "declaration": true,
"noImplicitReturns": true,
"baseUrl": ".",
"types": []
}, },
"include": [ "include": [
"typings/require.d.ts", "typings/require.d.ts",

View File

@@ -68,7 +68,7 @@ export const DataTransfers = {
FILES: 'Files', FILES: 'Files',
/** /**
* Typicaly transfer type for copy/paste transfers. * Typically transfer type for copy/paste transfers.
*/ */
TEXT: 'text/plain' TEXT: 'text/plain'
}; };

View File

@@ -467,28 +467,6 @@ export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
return document.defaultView!.getComputedStyle(el, null); return document.defaultView!.getComputedStyle(el, null);
} }
// Adapted from WinJS
// Converts a CSS positioning string for the specified element to pixels.
const convertToPixels: (element: HTMLElement, value: string) => number = (function () {
return function (element: HTMLElement, value: string): number {
return parseFloat(value) || 0;
};
})();
function getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number {
let computedStyle: CSSStyleDeclaration = getComputedStyle(element);
let value = '0';
if (computedStyle) {
if (computedStyle.getPropertyValue) {
value = computedStyle.getPropertyValue(cssPropertyName);
} else {
// IE8
value = (<any>computedStyle).getAttribute(jsPropertyName);
}
}
return convertToPixels(element, value);
}
export function getClientArea(element: HTMLElement): Dimension { export function getClientArea(element: HTMLElement): Dimension {
// Try with DOM clientWidth / clientHeight // Try with DOM clientWidth / clientHeight
@@ -514,48 +492,66 @@ export function getClientArea(element: HTMLElement): Dimension {
throw new Error('Unable to figure out browser width and height'); throw new Error('Unable to figure out browser width and height');
} }
const sizeUtils = { class SizeUtils {
// Adapted from WinJS
// Converts a CSS positioning string for the specified element to pixels.
private static convertToPixels(element: HTMLElement, value: string): number {
return parseFloat(value) || 0;
}
getBorderLeftWidth: function (element: HTMLElement): number { private static getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number {
return getDimension(element, 'border-left-width', 'borderLeftWidth'); let computedStyle: CSSStyleDeclaration = getComputedStyle(element);
}, let value = '0';
getBorderRightWidth: function (element: HTMLElement): number { if (computedStyle) {
return getDimension(element, 'border-right-width', 'borderRightWidth'); if (computedStyle.getPropertyValue) {
}, value = computedStyle.getPropertyValue(cssPropertyName);
getBorderTopWidth: function (element: HTMLElement): number { } else {
return getDimension(element, 'border-top-width', 'borderTopWidth'); // IE8
}, value = (<any>computedStyle).getAttribute(jsPropertyName);
getBorderBottomWidth: function (element: HTMLElement): number { }
return getDimension(element, 'border-bottom-width', 'borderBottomWidth'); }
}, return SizeUtils.convertToPixels(element, value);
}
getPaddingLeft: function (element: HTMLElement): number { static getBorderLeftWidth(element: HTMLElement): number {
return getDimension(element, 'padding-left', 'paddingLeft'); return SizeUtils.getDimension(element, 'border-left-width', 'borderLeftWidth');
}, }
getPaddingRight: function (element: HTMLElement): number { static getBorderRightWidth(element: HTMLElement): number {
return getDimension(element, 'padding-right', 'paddingRight'); return SizeUtils.getDimension(element, 'border-right-width', 'borderRightWidth');
}, }
getPaddingTop: function (element: HTMLElement): number { static getBorderTopWidth(element: HTMLElement): number {
return getDimension(element, 'padding-top', 'paddingTop'); return SizeUtils.getDimension(element, 'border-top-width', 'borderTopWidth');
}, }
getPaddingBottom: function (element: HTMLElement): number { static getBorderBottomWidth(element: HTMLElement): number {
return getDimension(element, 'padding-bottom', 'paddingBottom'); return SizeUtils.getDimension(element, 'border-bottom-width', 'borderBottomWidth');
}, }
getMarginLeft: function (element: HTMLElement): number { static getPaddingLeft(element: HTMLElement): number {
return getDimension(element, 'margin-left', 'marginLeft'); return SizeUtils.getDimension(element, 'padding-left', 'paddingLeft');
}, }
getMarginTop: function (element: HTMLElement): number { static getPaddingRight(element: HTMLElement): number {
return getDimension(element, 'margin-top', 'marginTop'); return SizeUtils.getDimension(element, 'padding-right', 'paddingRight');
}, }
getMarginRight: function (element: HTMLElement): number { static getPaddingTop(element: HTMLElement): number {
return getDimension(element, 'margin-right', 'marginRight'); return SizeUtils.getDimension(element, 'padding-top', 'paddingTop');
}, }
getMarginBottom: function (element: HTMLElement): number { static getPaddingBottom(element: HTMLElement): number {
return getDimension(element, 'margin-bottom', 'marginBottom'); return SizeUtils.getDimension(element, 'padding-bottom', 'paddingBottom');
}, }
__commaSentinel: false
}; static getMarginLeft(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-left', 'marginLeft');
}
static getMarginTop(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-top', 'marginTop');
}
static getMarginRight(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-right', 'marginRight');
}
static getMarginBottom(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-bottom', 'marginBottom');
}
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Position & Dimension // Position & Dimension
@@ -594,8 +590,8 @@ export function getTopLeftOffset(element: HTMLElement): { left: number; top: num
} }
if (element === offsetParent) { if (element === offsetParent) {
left += sizeUtils.getBorderLeftWidth(element); left += SizeUtils.getBorderLeftWidth(element);
top += sizeUtils.getBorderTopWidth(element); top += SizeUtils.getBorderTopWidth(element);
top += element.offsetTop; top += element.offsetTop;
left += element.offsetLeft; left += element.offsetLeft;
offsetParent = element.offsetParent; offsetParent = element.offsetParent;
@@ -686,33 +682,33 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
// Adapted from WinJS // Adapted from WinJS
// Gets the width of the element, including margins. // Gets the width of the element, including margins.
export function getTotalWidth(element: HTMLElement): number { export function getTotalWidth(element: HTMLElement): number {
let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element); let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
return element.offsetWidth + margin; return element.offsetWidth + margin;
} }
export function getContentWidth(element: HTMLElement): number { export function getContentWidth(element: HTMLElement): number {
let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element); let border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element);
let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element); let padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element);
return element.offsetWidth - border - padding; return element.offsetWidth - border - padding;
} }
export function getTotalScrollWidth(element: HTMLElement): number { export function getTotalScrollWidth(element: HTMLElement): number {
let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element); let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
return element.scrollWidth + margin; return element.scrollWidth + margin;
} }
// Adapted from WinJS // Adapted from WinJS
// Gets the height of the content of the specified element. The content height does not include borders or padding. // Gets the height of the content of the specified element. The content height does not include borders or padding.
export function getContentHeight(element: HTMLElement): number { export function getContentHeight(element: HTMLElement): number {
let border = sizeUtils.getBorderTopWidth(element) + sizeUtils.getBorderBottomWidth(element); let border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element);
let padding = sizeUtils.getPaddingTop(element) + sizeUtils.getPaddingBottom(element); let padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element);
return element.offsetHeight - border - padding; return element.offsetHeight - border - padding;
} }
// Adapted from WinJS // Adapted from WinJS
// Gets the height of the element, including its margins. // Gets the height of the element, including its margins.
export function getTotalHeight(element: HTMLElement): number { export function getTotalHeight(element: HTMLElement): number {
let margin = sizeUtils.getMarginTop(element) + sizeUtils.getMarginBottom(element); let margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element);
return element.offsetHeight + margin; return element.offsetHeight + margin;
} }
@@ -836,53 +832,53 @@ export function isHTMLElement(o: any): o is HTMLElement {
export const EventType = { export const EventType = {
// Mouse // Mouse
CLICK: 'click' as 'click', CLICK: 'click',
DBLCLICK: 'dblclick' as 'dblclick', DBLCLICK: 'dblclick',
MOUSE_UP: 'mouseup' as 'mouseup', MOUSE_UP: 'mouseup',
MOUSE_DOWN: 'mousedown' as 'mousedown', MOUSE_DOWN: 'mousedown',
MOUSE_OVER: 'mouseover' as 'mouseover', MOUSE_OVER: 'mouseover',
MOUSE_MOVE: 'mousemove' as 'mousemove', MOUSE_MOVE: 'mousemove',
MOUSE_OUT: 'mouseout' as 'mouseout', MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter' as 'mouseenter', MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave' as 'mouseleave', MOUSE_LEAVE: 'mouseleave',
CONTEXT_MENU: 'contextmenu' as 'contextmenu', CONTEXT_MENU: 'contextmenu',
WHEEL: 'wheel' as 'wheel', WHEEL: 'wheel',
// Keyboard // Keyboard
KEY_DOWN: 'keydown' as 'keydown', KEY_DOWN: 'keydown',
KEY_PRESS: 'keypress' as 'keypress', KEY_PRESS: 'keypress',
KEY_UP: 'keyup' as 'keyup', KEY_UP: 'keyup',
// HTML Document // HTML Document
LOAD: 'load' as 'load', LOAD: 'load',
UNLOAD: 'unload' as 'unload', UNLOAD: 'unload',
ABORT: 'abort' as 'abort', ABORT: 'abort',
ERROR: 'error' as 'error', ERROR: 'error',
RESIZE: 'resize' as 'resize', RESIZE: 'resize',
SCROLL: 'scroll' as 'scroll', SCROLL: 'scroll',
// Form // Form
SELECT: 'select' as 'select', SELECT: 'select',
CHANGE: 'change' as 'change', CHANGE: 'change',
SUBMIT: 'submit' as 'submit', SUBMIT: 'submit',
RESET: 'reset' as 'reset', RESET: 'reset',
FOCUS: 'focus' as 'focus', FOCUS: 'focus',
FOCUS_IN: 'focusin' as 'focusin', FOCUS_IN: 'focusin',
FOCUS_OUT: 'focusout' as 'focusout', FOCUS_OUT: 'focusout',
BLUR: 'blur' as 'blur', BLUR: 'blur',
INPUT: 'input' as 'input', INPUT: 'input',
// Local Storage // Local Storage
STORAGE: 'storage' as 'storage', STORAGE: 'storage',
// Drag // Drag
DRAG_START: 'dragstart' as 'dragstart', DRAG_START: 'dragstart',
DRAG: 'drag' as 'drag', DRAG: 'drag',
DRAG_ENTER: 'dragenter' as 'dragenter', DRAG_ENTER: 'dragenter',
DRAG_LEAVE: 'dragleave' as 'dragleave', DRAG_LEAVE: 'dragleave',
DRAG_OVER: 'dragover' as 'dragover', DRAG_OVER: 'dragover',
DROP: 'drop' as 'drop', DROP: 'drop',
DRAG_END: 'dragend' as 'dragend', DRAG_END: 'dragend',
// Animation // Animation
ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart', ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend', ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration' ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration'
}; } as const;
export interface EventLike { export interface EventLike {
preventDefault(): void; preventDefault(): void;

View File

@@ -214,10 +214,10 @@ export class Gesture extends Disposable {
} }
} }
private newGestureEvent(type: string, intialTarget?: EventTarget): GestureEvent { private newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent {
let event = <GestureEvent>(<any>document.createEvent('CustomEvent')); let event = <GestureEvent>(<any>document.createEvent('CustomEvent'));
event.initEvent(type, false, true); event.initEvent(type, false, true);
event.initialTarget = intialTarget; event.initialTarget = initialTarget;
return event; return event;
} }

View File

@@ -126,7 +126,7 @@ export class BreadcrumbsWidget {
this._pendingLayout.dispose(); this._pendingLayout.dispose();
} }
if (dim) { if (dim) {
// only meaure // only measure
this._pendingLayout = this._updateDimensions(dim); this._pendingLayout = this._updateDimensions(dim);
} else { } else {
this._pendingLayout = this._updateScrollbar(); this._pendingLayout = this._updateScrollbar();

View File

@@ -15,6 +15,10 @@
align-items: center; align-items: center;
} }
.monaco-workbench .dialog-modal-block.dimmed {
background: rgba(0, 0, 0, 0.3);
}
/** Dialog: Container */ /** Dialog: Container */
.monaco-workbench .dialog-box { .monaco-workbench .dialog-box {
display: flex; display: flex;
@@ -56,16 +60,22 @@
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
padding: 10px 15px 20px; padding: 10px 15px 20px;
align-items: center;
} }
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon { .monaco-workbench .dialog-box .dialog-message-row .dialog-icon {
flex: 0 0 30px; flex: 0 0 30px;
height: 30px;
padding-right: 4px; padding-right: 4px;
padding-left: 4px; padding-left: 4px;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending.svg');
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info { .vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info.svg'); background-image: url('info.svg');
} }
@@ -78,6 +88,10 @@
background-image: url('error.svg'); background-image: url('error.svg');
} }
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-dark.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info, .vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info,
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info { .hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info-inverse.svg'); background-image: url('info-inverse.svg');
@@ -93,6 +107,14 @@
background-image: url('error-inverse.svg'); background-image: url('error-inverse.svg');
} }
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-hc.svg');
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-size: 30px;
}
/** Dialog: Message Container */ /** Dialog: Message Container */
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container { .monaco-workbench .dialog-box .dialog-message-row .dialog-message-container {
display: flex; display: flex;

View File

@@ -19,7 +19,7 @@ import { mnemonicButtonLabel } from 'vs/base/common/labels';
export interface IDialogOptions { export interface IDialogOptions {
cancelId?: number; cancelId?: number;
detail?: string; detail?: string;
type?: 'none' | 'info' | 'error' | 'question' | 'warning'; type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
} }
export interface IDialogStyles extends IButtonStyles { export interface IDialogStyles extends IButtonStyles {
@@ -33,6 +33,7 @@ export class Dialog extends Disposable {
private element: HTMLElement | undefined; private element: HTMLElement | undefined;
private modal: HTMLElement | undefined; private modal: HTMLElement | undefined;
private buttonsContainer: HTMLElement | undefined; private buttonsContainer: HTMLElement | undefined;
private messageDetailElement: HTMLElement | undefined;
private iconElement: HTMLElement | undefined; private iconElement: HTMLElement | undefined;
private toolbarContainer: HTMLElement | undefined; private toolbarContainer: HTMLElement | undefined;
private buttonGroup: ButtonGroup | undefined; private buttonGroup: ButtonGroup | undefined;
@@ -40,7 +41,7 @@ export class Dialog extends Disposable {
constructor(private container: HTMLElement, private message: string, private buttons: string[], private options: IDialogOptions) { constructor(private container: HTMLElement, private message: string, private buttons: string[], private options: IDialogOptions) {
super(); super();
this.modal = this.container.appendChild($('.dialog-modal-block')); this.modal = this.container.appendChild($(`.dialog-modal-block${options.type === 'pending' ? '.dimmed' : ''}`));
this.element = this.modal.appendChild($('.dialog-box')); this.element = this.modal.appendChild($('.dialog-box'));
hide(this.element); hide(this.element);
@@ -56,13 +57,19 @@ export class Dialog extends Disposable {
messageElement.innerText = this.message; messageElement.innerText = this.message;
} }
const messageDetailElement = messageContainer.appendChild($('.dialog-message-detail')); this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
messageDetailElement.innerText = this.options.detail ? this.options.detail : message; this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row')); const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row'));
this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar')); this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar'));
} }
updateMessage(message: string): void {
if (this.messageDetailElement) {
this.messageDetailElement.innerText = message;
}
}
async show(): Promise<number> { async show(): Promise<number> {
return new Promise<number>((resolve) => { return new Promise<number>((resolve) => {
if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) { if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) {
@@ -129,6 +136,9 @@ export class Dialog extends Disposable {
case 'warning': case 'warning':
addClass(this.iconElement, 'icon-warning'); addClass(this.iconElement, 'icon-warning');
break; break;
case 'pending':
addClass(this.iconElement, 'icon-pending');
break;
case 'none': case 'none':
case 'info': case 'info':
case 'question': case 'question':

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:grey;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:white;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g>
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -502,7 +502,7 @@ function isMouseRightClick(event: UIEvent): boolean {
return event instanceof MouseEvent && event.button === 2; return event instanceof MouseEvent && event.button === 2;
} }
const DefaultMultipleSelectionContoller = { const DefaultMultipleSelectionController = {
isSelectionSingleChangeEvent, isSelectionSingleChangeEvent,
isSelectionRangeChangeEvent isSelectionRangeChangeEvent
}; };
@@ -529,7 +529,7 @@ export class MouseController<T> implements IDisposable {
this.multipleSelectionSupport = !(list.options.multipleSelectionSupport === false); this.multipleSelectionSupport = !(list.options.multipleSelectionSupport === false);
if (this.multipleSelectionSupport) { if (this.multipleSelectionSupport) {
this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionContoller; this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionController;
} }
this.openController = list.options.openController || DefaultOpenController; this.openController = list.options.openController || DefaultOpenController;
@@ -909,7 +909,7 @@ function getContiguousRangeContaining(range: number[], value: number): number[]
/** /**
* Given two sorted collections of numbers, returns the intersection * Given two sorted collections of numbers, returns the intersection
* betweem them (OR). * between them (OR).
*/ */
function disjunction(one: number[], other: number[]): number[] { function disjunction(one: number[], other: number[]): number[] {
const result: number[] = []; const result: number[] = [];

View File

@@ -1,7 +1,7 @@
@font-face { @font-face {
font-family: "octicons"; font-family: "octicons";
src: url("./octicons.ttf?4cd2299755e93a2430ba5703f4476584") format("truetype"), src: url("./octicons.ttf?91284a5a76ea88faeb754359b7f7cd03") format("truetype"),
url("./octicons.svg?4cd2299755e93a2430ba5703f4476584#octicons") format("svg"); url("./octicons.svg?91284a5a76ea88faeb754359b7f7cd03#octicons") format("svg");
} }
.octicon, .mega-octicon { .octicon, .mega-octicon {
@@ -240,4 +240,5 @@ url("./octicons.svg?4cd2299755e93a2430ba5703f4476584#octicons") format("svg");
.octicon-fold-up:before { content: "\f105" } .octicon-fold-up:before { content: "\f105" }
.octicon-github-action:before { content: "\f106" } .octicon-github-action:before { content: "\f106" }
.octicon-play:before { content: "\f107" } .octicon-play:before { content: "\f107" }
.octicon-request-changes:before { content: "\f108" } .octicon-remote:before { content: "\f108" }
.octicon-request-changes:before { content: "\f109" }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -523,7 +523,7 @@ export class DomScrollableElement extends ScrollableElement {
} }
public scanDomNode(): void { public scanDomNode(): void {
// widh, scrollLeft, scrollWidth, height, scrollTop, scrollHeight // width, scrollLeft, scrollWidth, height, scrollTop, scrollHeight
this.setScrollDimensions({ this.setScrollDimensions({
width: this._element.clientWidth, width: this._element.clientWidth,
scrollWidth: this._element.scrollWidth, scrollWidth: this._element.scrollWidth,

View File

@@ -33,7 +33,7 @@ export const enum TreeVisibility {
export interface ITreeFilterDataResult<TFilterData> { export interface ITreeFilterDataResult<TFilterData> {
/** /**
* Whether the node should be visibile. * Whether the node should be visible.
*/ */
visibility: boolean | TreeVisibility; visibility: boolean | TreeVisibility;

View File

@@ -5,6 +5,7 @@
import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json'; import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json';
import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter'; import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter';
import { mergeSort } from 'vs/base/common/arrays';
export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] { export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] {
@@ -158,6 +159,27 @@ export function applyEdit(text: string, edit: Edit): string {
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length); return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
} }
export function applyEdits(text: string, edits: Edit[]): string {
let sortedEdits = mergeSort(edits, (a, b) => {
const diff = a.offset - b.offset;
if (diff === 0) {
return a.length - b.length;
}
return diff;
});
let lastModifiedOffset = text.length;
for (let i = sortedEdits.length - 1; i >= 0; i--) {
let e = sortedEdits[i];
if (e.offset + e.length <= lastModifiedOffset) {
text = applyEdit(text, e);
} else {
throw new Error('Overlapping edit');
}
lastModifiedOffset = e.offset;
}
return text;
}
export function isWS(text: string, offset: number) { export function isWS(text: string, offset: number) {
return '\r\n \t'.indexOf(text.charAt(offset)) !== -1; return '\r\n \t'.indexOf(text.charAt(offset)) !== -1;
} }

View File

@@ -226,7 +226,7 @@ export class URI implements UriComponents {
// ---- modify to new ------------------------- // ---- modify to new -------------------------
public with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI { with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
if (!change) { if (!change) {
return this; return this;
@@ -279,7 +279,7 @@ export class URI implements UriComponents {
* *
* @param value A string which represents an URI (see `URI#toString`). * @param value A string which represents an URI (see `URI#toString`).
*/ */
public static parse(value: string, _strict: boolean = false): URI { static parse(value: string, _strict: boolean = false): URI {
const match = _regexp.exec(value); const match = _regexp.exec(value);
if (!match) { if (!match) {
return new _URI(_empty, _empty, _empty, _empty, _empty); return new _URI(_empty, _empty, _empty, _empty, _empty);
@@ -315,7 +315,7 @@ export class URI implements UriComponents {
* *
* @param path A file system path (see `URI#fsPath`) * @param path A file system path (see `URI#fsPath`)
*/ */
public static file(path: string): URI { static file(path: string): URI {
let authority = _empty; let authority = _empty;
@@ -342,7 +342,7 @@ export class URI implements UriComponents {
return new _URI('file', authority, path, _empty, _empty); return new _URI('file', authority, path, _empty, _empty);
} }
public static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI { static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
return new _URI( return new _URI(
components.scheme, components.scheme,
components.authority, components.authority,
@@ -365,17 +365,22 @@ export class URI implements UriComponents {
* *
* @param skipEncoding Do not encode the result, default is `false` * @param skipEncoding Do not encode the result, default is `false`
*/ */
public toString(skipEncoding: boolean = false): string { toString(skipEncoding: boolean = false): string {
return _asFormatted(this, skipEncoding); return _asFormatted(this, skipEncoding);
} }
public toJSON(): object { toJSON(): UriComponents {
return this; return this;
} }
static revive(data: UriComponents | any): URI { static revive(data: UriComponents | URI): URI;
static revive(data: UriComponents | URI | undefined): URI | undefined;
static revive(data: UriComponents | URI | null): URI | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null {
if (!data) { if (!data) {
return data; // {{SQL CARBON EDIT}} @todo chlafren change back to data when we enable strict null checks
return undefined;
} else if (data instanceof URI) { } else if (data instanceof URI) {
return data; return data;
} else { } else {
@@ -415,7 +420,7 @@ class _URI extends URI {
return this._fsPath; return this._fsPath;
} }
public toString(skipEncoding: boolean = false): string { toString(skipEncoding: boolean = false): string {
if (!skipEncoding) { if (!skipEncoding) {
if (!this._formatted) { if (!this._formatted) {
this._formatted = _asFormatted(this, false); this._formatted = _asFormatted(this, false);
@@ -427,7 +432,7 @@ class _URI extends URI {
} }
} }
toJSON(): object { toJSON(): UriComponents {
const res = <UriState>{ const res = <UriState>{
$mid: 1 $mid: 1
}; };

View File

@@ -14,6 +14,10 @@ export const UTF8_with_bom = 'utf8bom';
export const UTF16be = 'utf16be'; export const UTF16be = 'utf16be';
export const UTF16le = 'utf16le'; export const UTF16le = 'utf16le';
export const UTF16be_BOM = [0xFE, 0xFF];
export const UTF16le_BOM = [0xFF, 0xFE];
export const UTF8_BOM = [0xEF, 0xBB, 0xBF];
export interface IDecodeStreamOptions { export interface IDecodeStreamOptions {
guessEncoding?: boolean; guessEncoding?: boolean;
minBytesRequiredForDetection?: number; minBytesRequiredForDetection?: number;
@@ -150,12 +154,12 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
const b1 = buffer.readUInt8(1); const b1 = buffer.readUInt8(1);
// UTF-16 BE // UTF-16 BE
if (b0 === 0xFE && b1 === 0xFF) { if (b0 === UTF16be_BOM[0] && b1 === UTF16be_BOM[1]) {
return UTF16be; return UTF16be;
} }
// UTF-16 LE // UTF-16 LE
if (b0 === 0xFF && b1 === 0xFE) { if (b0 === UTF16le_BOM[0] && b1 === UTF16le_BOM[1]) {
return UTF16le; return UTF16le;
} }
@@ -166,7 +170,7 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
const b2 = buffer.readUInt8(2); const b2 = buffer.readUInt8(2);
// UTF-8 // UTF-8
if (b0 === 0xEF && b1 === 0xBB && b2 === 0xBF) { if (b0 === UTF8_BOM[0] && b1 === UTF8_BOM[1] && b2 === UTF8_BOM[2]) {
return UTF8; return UTF8;
} }
@@ -178,7 +182,7 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
* If no BOM is detected, null will be passed to callback. * If no BOM is detected, null will be passed to callback.
*/ */
export function detectEncodingByBOM(file: string): Promise<string | null> { export function detectEncodingByBOM(file: string): Promise<string | null> {
return stream.readExactlyByFile(file, 3).then(({ buffer, bytesRead }) => detectEncodingByBOMFromBuffer(buffer, bytesRead)); return stream.readExactlyByFile(file, 3).then(({ buffer, bytesRead }) => detectEncodingByBOMFromBuffer(buffer, bytesRead), error => null);
} }
const MINIMUM_THRESHOLD = 0.2; const MINIMUM_THRESHOLD = 0.2;

39
src/vs/base/node/ps.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
PAGESIZE=`getconf PAGESIZE`;
TOTAL_MEMORY=`cat /proc/meminfo | head -n 1 | awk '{print $2}'`;
# Mimic the output of ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
# Read all numeric subdirectories in /proc
for pid in `cd /proc && ls -d [0-9]*`
do {
if [ -e /proc/$pid/stat ]
then
echo $pid;
# ppid is the word at index 4 in the stat file for the process
awk '{print $4}' /proc/$pid/stat;
# pcpu - calculation will be done later, this is a placeholder value
echo "0.0"
# pmem - ratio of the process's working set size to total memory.
# use the page size to convert to bytes, total memory is in KB
# multiplied by 100 to get percentage, extra 10 to be able to move
# the decimal over by one place
RESIDENT_SET_SIZE=`awk '{print $24}' /proc/$pid/stat`;
PERCENT_MEMORY=$(((1000 * $PAGESIZE * $RESIDENT_SET_SIZE) / ($TOTAL_MEMORY * 1024)));
if [ $PERCENT_MEMORY -lt 10 ]
then
# replace the last character with 0. the last character
echo $PERCENT_MEMORY | sed 's/.$/0.&/'; #pmem
else
# insert . before the last character
echo $PERCENT_MEMORY | sed 's/.$/.&/';
fi
# cmdline
xargs -0 < /proc/$pid/cmdline;
fi
} | tr "\n" "\t"; # Replace newlines with tab so that all info for a process is shown on one line
echo; # But add new lines between processes
done

View File

@@ -14,6 +14,7 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
let rootItem: ProcessItem | undefined; let rootItem: ProcessItem | undefined;
const map = new Map<number, ProcessItem>(); const map = new Map<number, ProcessItem>();
function addToTree(pid: number, ppid: number, cmd: string, load: number, mem: number) { function addToTree(pid: number, ppid: number, cmd: string, load: number, mem: number) {
const parent = map.get(ppid); const parent = map.get(ppid);
@@ -162,64 +163,87 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
}, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory); }, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory);
}); });
} else { // OS X & Linux } else { // OS X & Linux
function calculateLinuxCpuUsage() {
const CMD = '/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command='; // Flatten rootItem to get a list of all VSCode processes
const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/; let processes = [rootItem];
const pids: number[] = [];
// Set numeric locale to ensure '.' is used as the decimal separator while (processes.length) {
exec(CMD, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => { const process = processes.shift();
if (process) {
if (err || stderr) { pids.push(process.pid);
reject(err || new Error(stderr.toString())); if (process.children) {
} else { processes = processes.concat(process.children);
const lines = stdout.toString().split('\n');
for (const line of lines) {
const matches = PID_CMD.exec(line.trim());
if (matches && matches.length === 6) {
addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4]));
} }
} }
}
if (process.platform === 'linux') { // The cpu usage value reported on Linux is the average over the process lifetime,
// Flatten rootItem to get a list of all VSCode processes // recalculate the usage over a one second interval
let processes = [rootItem]; // JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803
const pids: number[] = []; let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh'));
while (processes.length) { cmd += ' ' + pids.join(' ');
const process = processes.shift();
if (process) { exec(cmd, {}, (err, stdout, stderr) => {
pids.push(process.pid); if (err || stderr) {
if (process.children) { reject(err || new Error(stderr.toString()));
processes = processes.concat(process.children); } else {
} const cpuUsage = stdout.toString().split('\n');
} for (let i = 0; i < pids.length; i++) {
const processInfo = map.get(pids[i])!;
processInfo.load = parseFloat(cpuUsage[i]);
} }
// The cpu usage value reported on Linux is the average over the process lifetime, resolve(rootItem);
// recalculate the usage over a one second interval }
// JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803 });
let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh')); }
cmd += ' ' + pids.join(' ');
exec('which ps', {}, (err, stdout, stderr) => {
if (err || stderr) {
if (process.platform !== 'linux') {
reject(err || new Error(stderr.toString()));
} else {
const cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/ps.sh'));
exec(cmd, {}, (err, stdout, stderr) => { exec(cmd, {}, (err, stdout, stderr) => {
if (err || stderr) { if (err || stderr) {
reject(err || new Error(stderr.toString())); reject(err || new Error(stderr.toString()));
} else { } else {
const cpuUsage = stdout.toString().split('\n'); parsePsOutput(stdout, addToTree);
for (let i = 0; i < pids.length; i++) { calculateLinuxCpuUsage();
const processInfo = map.get(pids[i])!;
processInfo.load = parseFloat(cpuUsage[i]);
}
resolve(rootItem);
} }
}); });
} else {
resolve(rootItem);
} }
} else {
const ps = stdout.toString().trim();
const args = '-ax -o pid=,ppid=,pcpu=,pmem=,command=';
// Set numeric locale to ensure '.' is used as the decimal separator
exec(`${ps} ${args}`, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => {
if (err || stderr) {
reject(err || new Error(stderr.toString()));
} else {
parsePsOutput(stdout, addToTree);
if (process.platform === 'linux') {
calculateLinuxCpuUsage();
} else {
resolve(rootItem);
}
}
});
} }
}); });
} }
}); });
} }
function parsePsOutput(stdout: string, addToTree: (pid: number, ppid: number, cmd: string, load: number, mem: number) => void): void {
const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/;
const lines = stdout.toString().split('\n');
for (const line of lines) {
const matches = PID_CMD.exec(line.trim());
if (matches && matches.length === 6) {
addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4]));
}
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as assert from 'assert'; import * as assert from 'assert';
import { URI } from 'vs/base/common/uri'; import { URI, UriComponents } from 'vs/base/common/uri';
import { isWindows } from 'vs/base/common/platform'; import { isWindows } from 'vs/base/common/platform';
@@ -441,7 +441,7 @@ suite('URI', () => {
// let c = 100000; // let c = 100000;
// while (c-- > 0) { // while (c-- > 0) {
for (let value of values) { for (let value of values) {
let data = value.toJSON(); let data = value.toJSON() as UriComponents;
let clone = URI.revive(data); let clone = URI.revive(data);
assert.equal(clone.scheme, value.scheme); assert.equal(clone.scheme, value.scheme);

View File

@@ -11,6 +11,14 @@ import { Readable } from 'stream';
import { getPathFromAmdModule } from 'vs/base/common/amd'; import { getPathFromAmdModule } from 'vs/base/common/amd';
suite('Encoding', () => { suite('Encoding', () => {
test('detectBOM does not return error for non existing file', async () => {
const file = getPathFromAmdModule(require, './fixtures/not-exist.css');
const detectedEncoding = await encoding.detectEncodingByBOM(file);
assert.equal(detectedEncoding, null);
});
test('detectBOM UTF-8', async () => { test('detectBOM UTF-8', async () => {
const file = getPathFromAmdModule(require, './fixtures/some_utf8.css'); const file = getPathFromAmdModule(require, './fixtures/some_utf8.css');

View File

@@ -8,7 +8,8 @@ import { getMachineId } from 'vs/base/node/id';
suite('ID', () => { suite('ID', () => {
test('getMachineId', () => { test('getMachineId', function () {
this.timeout(20000);
return getMachineId().then(id => { return getMachineId().then(id => {
assert.ok(id); assert.ok(id);
}); });

View File

@@ -60,6 +60,7 @@ export function startup(configuration: IssueReporterConfiguration) {
const issueReporter = new IssueReporter(configuration); const issueReporter = new IssueReporter(configuration);
issueReporter.render(); issueReporter.render();
document.body.style.display = 'block'; document.body.style.display = 'block';
issueReporter.setInitialFocus();
} }
export class IssueReporter extends Disposable { export class IssueReporter extends Disposable {
@@ -88,6 +89,8 @@ export class IssueReporter extends Disposable {
os: `${os.type()} ${os.arch()} ${os.release()}${isSnap ? ' snap' : ''}` os: `${os.type()} ${os.arch()} ${os.release()}${isSnap ? ' snap' : ''}`
}, },
extensionsDisabled: !!this.environmentService.disableExtensions, extensionsDisabled: !!this.environmentService.disableExtensions,
fileOnExtension: configuration.data.extensionId ? true : undefined,
selectedExtension: configuration.data.extensionId ? configuration.data.enabledExtensions.filter(extension => extension.id === configuration.data.extensionId)[0] : undefined
}); });
const issueReporterElement = this.getElementById('issue-reporter'); const issueReporterElement = this.getElementById('issue-reporter');
@@ -140,6 +143,21 @@ export class IssueReporter extends Disposable {
this.renderBlocks(); this.renderBlocks();
} }
setInitialFocus() {
const { fileOnExtension } = this.issueReporterModel.getData();
if (fileOnExtension) {
const issueTitle = document.getElementById('issue-title');
if (issueTitle) {
issueTitle.focus();
}
} else {
const issueType = document.getElementById('issue-type');
if (issueType) {
issueType.focus();
}
}
}
private applyZoom(zoomLevel: number) { private applyZoom(zoomLevel: number) {
webFrame.setZoomLevel(zoomLevel); webFrame.setZoomLevel(zoomLevel);
browser.setZoomFactor(webFrame.getZoomFactor()); browser.setZoomFactor(webFrame.getZoomFactor());
@@ -699,9 +717,13 @@ export class IssueReporter extends Disposable {
private setSourceOptions(): void { private setSourceOptions(): void {
const sourceSelect = this.getElementById('issue-source')! as HTMLSelectElement; const sourceSelect = this.getElementById('issue-source')! as HTMLSelectElement;
const selected = sourceSelect.selectedIndex; const { issueType, fileOnExtension } = this.issueReporterModel.getData();
let selected = sourceSelect.selectedIndex;
if (selected === -1 && fileOnExtension !== undefined) {
selected = fileOnExtension ? 2 : 1;
}
sourceSelect.innerHTML = ''; sourceSelect.innerHTML = '';
const { issueType } = this.issueReporterModel.getData();
if (issueType === IssueType.FeatureRequest) { if (issueType === IssueType.FeatureRequest) {
sourceSelect.append(...[ sourceSelect.append(...[
this.makeOption('', localize('selectSource', "Select source"), true), this.makeOption('', localize('selectSource', "Select source"), true),
@@ -961,10 +983,15 @@ export class IssueReporter extends Disposable {
return 0; return 0;
}); });
const makeOption = (extension: IOption) => `<option value="${extension.id}">${escape(extension.name)}</option>`; const makeOption = (extension: IOption, selectedExtension?: IssueReporterExtensionData) => {
const selected = selectedExtension && extension.id === selectedExtension.id;
return `<option value="${extension.id}" ${selected ? 'selected' : ''}>${escape(extension.name)}</option>`;
};
const extensionsSelector = this.getElementById('extension-selector'); const extensionsSelector = this.getElementById('extension-selector');
if (extensionsSelector) { if (extensionsSelector) {
extensionsSelector.innerHTML = '<option></option>' + extensionOptions.map(makeOption).join('\n'); const { selectedExtension } = this.issueReporterModel.getData();
extensionsSelector.innerHTML = '<option></option>' + extensionOptions.map(extension => makeOption(extension, selectedExtension)).join('\n');
this.addEventListener('extension-selector', 'change', (e: Event) => { this.addEventListener('extension-selector', 'change', (e: Event) => {
const selectedExtensionId = (<HTMLInputElement>e.target).value; const selectedExtensionId = (<HTMLInputElement>e.target).value;

View File

@@ -29,8 +29,8 @@ const collapsedStateCache: Map<string, boolean> = new Map<string, boolean>();
let lastRequestTime: number; let lastRequestTime: number;
interface FormattedProcessItem { interface FormattedProcessItem {
cpu: string; cpu: number;
memory: string; memory: number;
pid: string; pid: string;
name: string; name: string;
formattedName: string; formattedName: string;
@@ -66,8 +66,8 @@ function getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, in
const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`; const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`;
const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100)); const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100));
processes.push({ processes.push({
cpu: item.load.toFixed(0), cpu: item.load,
memory: (memory / MB).toFixed(0), memory: (memory / MB),
pid: item.pid.toFixed(0), pid: item.pid.toFixed(0),
name, name,
formattedName, formattedName,
@@ -202,13 +202,13 @@ function renderTableSection(sectionName: string, processList: FormattedProcessIt
p.pid === highestCPUProcess p.pid === highestCPUProcess
? cpu.classList.add('centered', 'highest') ? cpu.classList.add('centered', 'highest')
: cpu.classList.add('centered'); : cpu.classList.add('centered');
cpu.textContent = p.cpu.toString(); cpu.textContent = p.cpu.toFixed(0);
const memory = document.createElement('td'); const memory = document.createElement('td');
p.pid === highestMemoryProcess p.pid === highestMemoryProcess
? memory.classList.add('centered', 'highest') ? memory.classList.add('centered', 'highest')
: memory.classList.add('centered'); : memory.classList.add('centered');
memory.textContent = p.memory; memory.textContent = p.memory.toFixed(0);
const pid = document.createElement('td'); const pid = document.createElement('td');
pid.classList.add('centered'); pid.classList.add('centered');

View File

@@ -1754,7 +1754,7 @@ export class EditorModeContext extends Disposable {
this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model)); this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model));
this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model)); this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model)); this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length > 1 || modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1); this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length + modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1); this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet); this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
}); });

View File

@@ -368,9 +368,6 @@ export class ReferenceWidget extends PeekViewWidget {
if (e.browserEvent instanceof KeyboardEvent) { if (e.browserEvent instanceof KeyboardEvent) {
// todo@joh make this a command // todo@joh make this a command
goto = true; goto = true;
} else if (e.browserEvent instanceof MouseEvent) {
aside = e.browserEvent.ctrlKey || e.browserEvent.metaKey || e.browserEvent.altKey;
goto = e.browserEvent.detail === 2;
} }
if (aside) { if (aside) {
onEvent(e.elements[0], 'side'); onEvent(e.elements[0], 'side');

View File

@@ -197,7 +197,7 @@ export class SnippetController2 implements IEditorContribution {
insertText: option.value, insertText: option.value,
// insertText: `\${1|${after.concat(before).join(',')}|}$0`, // insertText: `\${1|${after.concat(before).join(',')}|}$0`,
// snippetType: 'textmate', // snippetType: 'textmate',
sortText: repeat('a', i), sortText: repeat('a', i + 1),
range: Range.fromPositions(this._editor.getPosition()!, this._editor.getPosition()!.delta(0, first.value.length)) range: Range.fromPositions(this._editor.getPosition()!, this._editor.getPosition()!.delta(0, first.value.length))
}; };
})); }));

View File

@@ -343,7 +343,7 @@ export class SuggestModel implements IDisposable {
const position = this._editor.getPosition(); const position = this._editor.getPosition();
const ctx = new LineContext(model, position, this._state === State.Auto, false); const ctx = new LineContext(model, position, this._state === State.Auto, false);
this._onNewContext(ctx); this._onNewContext(ctx);
}, 25); }, 0);
} }
trigger(context: SuggestTriggerContext, retrigger: boolean = false, onlyFrom?: Set<CompletionItemProvider>, existingItems?: CompletionItem[]): void { trigger(context: SuggestTriggerContext, retrigger: boolean = false, onlyFrom?: Set<CompletionItemProvider>, existingItems?: CompletionItem[]): void {

View File

@@ -496,6 +496,9 @@ export class StandaloneTelemetryService implements ITelemetryService {
public isOptedIn = false; public isOptedIn = false;
public setEnabled(value: boolean): void {
}
public publicLog(eventName: string, data?: any): Promise<void> { public publicLog(eventName: string, data?: any): Promise<void> {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }

7
src/vs/monaco.d.ts vendored
View File

@@ -171,8 +171,11 @@ declare namespace monaco {
* @param skipEncoding Do not encode the result, default is `false` * @param skipEncoding Do not encode the result, default is `false`
*/ */
toString(skipEncoding?: boolean): string; toString(skipEncoding?: boolean): string;
toJSON(): object; toJSON(): UriComponents;
static revive(data: UriComponents | any): Uri; static revive(data: UriComponents | Uri): Uri;
static revive(data: UriComponents | Uri | undefined): Uri | undefined;
static revive(data: UriComponents | Uri | null): Uri | null;
static revive(data: UriComponents | Uri | undefined | null): Uri | undefined | null;
} }
export interface UriComponents { export interface UriComponents {

View File

@@ -83,8 +83,21 @@ export interface IConfigurationRegistry {
} }
export const enum ConfigurationScope { export const enum ConfigurationScope {
/**
* Application specific configuration, which can be configured only in local user settings.
*/
APPLICATION = 1, APPLICATION = 1,
/**
* Machine specific configuration, which can be configured only in local and remote user settings.
*/
MACHINE,
/**
* Window specific configuration, which can be configured in the user or workspace settings.
*/
WINDOW, WINDOW,
/**
* Resource specific configuration, which can be configured in the user, workspace or folder settings.
*/
RESOURCE, RESOURCE,
} }
@@ -95,6 +108,10 @@ export interface IConfigurationPropertySchema extends IJSONSchema {
tags?: string[]; tags?: string[];
} }
export interface IConfigurationExtensionInfo {
id: string;
}
export interface IConfigurationNode { export interface IConfigurationNode {
id?: string; id?: string;
order?: number; order?: number;
@@ -105,7 +122,7 @@ export interface IConfigurationNode {
allOf?: IConfigurationNode[]; allOf?: IConfigurationNode[];
overridable?: boolean; overridable?: boolean;
scope?: ConfigurationScope; scope?: ConfigurationScope;
contributedByExtension?: boolean; extensionInfo?: IConfigurationExtensionInfo;
} }
export interface IDefaultConfigurationExtension { export interface IDefaultConfigurationExtension {
@@ -116,6 +133,7 @@ export interface IDefaultConfigurationExtension {
export const allSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const allSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const applicationSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const applicationSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const machineSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const windowSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const windowSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const resourceSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const resourceSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
@@ -186,6 +204,9 @@ class ConfigurationRegistry implements IConfigurationRegistry {
case ConfigurationScope.APPLICATION: case ConfigurationScope.APPLICATION:
delete applicationSettings.properties[key]; delete applicationSettings.properties[key];
break; break;
case ConfigurationScope.MACHINE:
delete machineSettings.properties[key];
break;
case ConfigurationScope.WINDOW: case ConfigurationScope.WINDOW:
delete windowSettings.properties[key]; delete windowSettings.properties[key];
break; break;
@@ -334,6 +355,9 @@ class ConfigurationRegistry implements IConfigurationRegistry {
case ConfigurationScope.APPLICATION: case ConfigurationScope.APPLICATION:
applicationSettings.properties[key] = properties[key]; applicationSettings.properties[key] = properties[key];
break; break;
case ConfigurationScope.MACHINE:
machineSettings.properties[key] = properties[key];
break;
case ConfigurationScope.WINDOW: case ConfigurationScope.WINDOW:
windowSettings.properties[key] = properties[key]; windowSettings.properties[key] = properties[key];
break; break;
@@ -371,6 +395,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
delete allSettings.patternProperties[this.overridePropertyPattern]; delete allSettings.patternProperties[this.overridePropertyPattern];
delete applicationSettings.patternProperties[this.overridePropertyPattern]; delete applicationSettings.patternProperties[this.overridePropertyPattern];
delete machineSettings.patternProperties[this.overridePropertyPattern];
delete windowSettings.patternProperties[this.overridePropertyPattern]; delete windowSettings.patternProperties[this.overridePropertyPattern];
delete resourceSettings.patternProperties[this.overridePropertyPattern]; delete resourceSettings.patternProperties[this.overridePropertyPattern];
@@ -378,6 +403,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
allSettings.patternProperties[this.overridePropertyPattern] = patternProperties; allSettings.patternProperties[this.overridePropertyPattern] = patternProperties;
applicationSettings.patternProperties[this.overridePropertyPattern] = patternProperties; applicationSettings.patternProperties[this.overridePropertyPattern] = patternProperties;
machineSettings.patternProperties[this.overridePropertyPattern] = patternProperties;
windowSettings.patternProperties[this.overridePropertyPattern] = patternProperties; windowSettings.patternProperties[this.overridePropertyPattern] = patternProperties;
resourceSettings.patternProperties[this.overridePropertyPattern] = patternProperties; resourceSettings.patternProperties[this.overridePropertyPattern] = patternProperties;

View File

@@ -18,7 +18,6 @@ export interface ParsedArgs {
waitMarkerFilePath?: string; waitMarkerFilePath?: string;
diff?: boolean; diff?: boolean;
add?: boolean; add?: boolean;
gitCredential?: string;
goto?: boolean; goto?: boolean;
'new-window'?: boolean; 'new-window'?: boolean;
'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch. 'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch.

View File

@@ -197,7 +197,7 @@ function wrapText(text: string, columns: number): string[] {
return lines; return lines;
} }
export function buildHelpMessage(productName: string, executableName: string, version: string, isOptionSupported = (_: Option) => true): string { export function buildHelpMessage(productName: string, executableName: string, version: string, isOptionSupported = (_: Option) => true, isPipeSupported = true): string {
const columns = (process.stdout).isTTY && (process.stdout).columns || 80; const columns = (process.stdout).isTTY && (process.stdout).columns || 80;
let categories = new HelpCategories(); let categories = new HelpCategories();

View File

@@ -86,7 +86,7 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
get onDidUninstallExtension(): Event<DidUninstallExtensionEvent> { return this.channel.listen('onDidUninstallExtension'); } get onDidUninstallExtension(): Event<DidUninstallExtensionEvent> { return this.channel.listen('onDidUninstallExtension'); }
zip(extension: ILocalExtension): Promise<URI> { zip(extension: ILocalExtension): Promise<URI> {
return Promise.resolve(this.channel.call('zip', [extension]).then(result => URI.revive(result))); return Promise.resolve(this.channel.call('zip', [extension]).then(result => URI.revive(<UriComponents>result)));
} }
unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> { unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> {
@@ -122,4 +122,4 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
getExtensionsReport(): Promise<IReportedExtension[]> { getExtensionsReport(): Promise<IReportedExtension[]> {
return Promise.resolve(this.channel.call('getExtensionsReport')); return Promise.resolve(this.channel.call('getExtensionsReport'));
} }
} }

View File

@@ -124,11 +124,6 @@ export interface IFileService {
*/ */
resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise<IStreamContent>; resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise<IStreamContent>;
/**
* @deprecated use writeFile instead
*/
updateContent(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<IFileStatWithMetadata>;
/** /**
* Updates the content replacing its previous value. * Updates the content replacing its previous value.
*/ */
@@ -148,18 +143,13 @@ export interface IFileService {
*/ */
copy(source: URI, target: URI, overwrite?: boolean): Promise<IFileStatWithMetadata>; copy(source: URI, target: URI, overwrite?: boolean): Promise<IFileStatWithMetadata>;
/**
* @deprecated use createFile2 instead
*/
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStatWithMetadata>;
/** /**
* Creates a new file with the given path and optional contents. The returned promise * Creates a new file with the given path and optional contents. The returned promise
* will have the stat model object as a result. * will have the stat model object as a result.
* *
* The optional parameter content can be used as value to fill into the new file. * The optional parameter content can be used as value to fill into the new file.
*/ */
createFile2(resource: URI, bufferOrReadable?: VSBuffer | VSBufferReadable, options?: ICreateFileOptions): Promise<IFileStatWithMetadata>; createFile(resource: URI, bufferOrReadable?: VSBuffer | VSBufferReadable, options?: ICreateFileOptions): Promise<IFileStatWithMetadata>;
/** /**
* Creates a new folder with the given path. The returned promise * Creates a new folder with the given path. The returned promise
@@ -666,6 +656,7 @@ export interface ITextSnapshot {
*/ */
export function snapshotToString(snapshot: ITextSnapshot): string { export function snapshotToString(snapshot: ITextSnapshot): string {
const chunks: string[] = []; const chunks: string[] = [];
let chunk: string | null; let chunk: string | null;
while (typeof (chunk = snapshot.read()) === 'string') { while (typeof (chunk = snapshot.read()) === 'string') {
chunks.push(chunk); chunks.push(chunk);
@@ -674,6 +665,22 @@ export function snapshotToString(snapshot: ITextSnapshot): string {
return chunks.join(''); return chunks.join('');
} }
export function stringToSnapshot(value: string): ITextSnapshot {
let done = false;
return {
read(): string | null {
if (!done) {
done = true;
return value;
}
return null;
}
};
}
export class TextSnapshotReadable implements VSBufferReadable { export class TextSnapshotReadable implements VSBufferReadable {
private preambleHandled: boolean; private preambleHandled: boolean;
@@ -703,6 +710,22 @@ export class TextSnapshotReadable implements VSBufferReadable {
} }
} }
export function toBufferOrReadable(value: string): VSBuffer;
export function toBufferOrReadable(value: ITextSnapshot): VSBufferReadable;
export function toBufferOrReadable(value: string | ITextSnapshot): VSBuffer | VSBufferReadable;
export function toBufferOrReadable(value: string | ITextSnapshot | undefined): VSBuffer | VSBufferReadable | undefined;
export function toBufferOrReadable(value: string | ITextSnapshot | undefined): VSBuffer | VSBufferReadable | undefined {
if (typeof value === 'undefined') {
return undefined;
}
if (typeof value === 'string') {
return VSBuffer.fromString(value);
}
return new TextSnapshotReadable(value);
}
/** /**
* Streamable content and meta information of a file. * Streamable content and meta information of a file.
*/ */
@@ -1158,8 +1181,4 @@ export interface ILegacyFileService extends IDisposable {
resolveContent(resource: URI, options?: IResolveContentOptions): Promise<IContent>; resolveContent(resource: URI, options?: IResolveContentOptions): Promise<IContent>;
resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise<IStreamContent>; resolveStreamContent(resource: URI, options?: IResolveContentOptions): Promise<IStreamContent>;
updateContent(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<IFileStatWithMetadata>;
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStatWithMetadata>;
} }

View File

@@ -15,7 +15,7 @@ import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { IWorkspaceIdentifier, IWorkspacesMainService, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceIdentifier, IWorkspacesMainService, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IHistoryMainService, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile } from 'vs/platform/history/common/history'; import { IHistoryMainService, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile } from 'vs/platform/history/common/history';
import { ThrottledDelayer } from 'vs/base/common/async'; import { ThrottledDelayer } from 'vs/base/common/async';
import { isEqual as areResourcesEqual, dirname, originalFSPath } from 'vs/base/common/resources'; import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -29,6 +29,12 @@ export class HistoryMainService implements IHistoryMainService {
private static readonly MAX_MACOS_DOCK_RECENT_FOLDERS = 10; private static readonly MAX_MACOS_DOCK_RECENT_FOLDERS = 10;
private static readonly MAX_MACOS_DOCK_RECENT_FILES = 5; private static readonly MAX_MACOS_DOCK_RECENT_FILES = 5;
// Exclude some very common files from the dock/taskbar
private static readonly COMMON_FILES_FILTER = [
'COMMIT_EDITMSG',
'MERGE_MSG'
];
private static readonly recentlyOpenedStorageKey = 'openedPathsList'; private static readonly recentlyOpenedStorageKey = 'openedPathsList';
_serviceBrand: any; _serviceBrand: any;
@@ -52,17 +58,29 @@ export class HistoryMainService implements IHistoryMainService {
const files: IRecentFile[] = []; const files: IRecentFile[] = [];
for (let curr of newlyAdded) { for (let curr of newlyAdded) {
// Workspace
if (isRecentWorkspace(curr)) { if (isRecentWorkspace(curr)) {
if (!this.workspacesMainService.isUntitledWorkspace(curr.workspace) && indexOfWorkspace(workspaces, curr.workspace) === -1) { if (!this.workspacesMainService.isUntitledWorkspace(curr.workspace) && indexOfWorkspace(workspaces, curr.workspace) === -1) {
workspaces.push(curr); workspaces.push(curr);
} }
} else if (isRecentFolder(curr)) { }
// Folder
else if (isRecentFolder(curr)) {
if (indexOfFolder(workspaces, curr.folderUri) === -1) { if (indexOfFolder(workspaces, curr.folderUri) === -1) {
workspaces.push(curr); workspaces.push(curr);
} }
} else { }
if (indexOfFile(files, curr.fileUri) === -1) {
// File
else {
const alreadyExistsInHistory = indexOfFile(files, curr.fileUri) >= 0;
const shouldBeFiltered = curr.fileUri.scheme === Schemas.file && HistoryMainService.COMMON_FILES_FILTER.indexOf(basename(curr.fileUri)) >= 0;
if (!alreadyExistsInHistory && !shouldBeFiltered) {
files.push(curr); files.push(curr);
// Add to recent documents (Windows only, macOS later) // Add to recent documents (Windows only, macOS later)
if (isWindows && curr.fileUri.scheme === Schemas.file) { if (isWindows && curr.fileUri.scheme === Schemas.file) {
app.addRecentDocument(curr.fileUri.fsPath); app.addRecentDocument(curr.fileUri.fsPath);
@@ -76,6 +94,7 @@ export class HistoryMainService implements IHistoryMainService {
if (workspaces.length > HistoryMainService.MAX_TOTAL_RECENT_ENTRIES) { if (workspaces.length > HistoryMainService.MAX_TOTAL_RECENT_ENTRIES) {
workspaces.length = HistoryMainService.MAX_TOTAL_RECENT_ENTRIES; workspaces.length = HistoryMainService.MAX_TOTAL_RECENT_ENTRIES;
} }
if (files.length > HistoryMainService.MAX_TOTAL_RECENT_ENTRIES) { if (files.length > HistoryMainService.MAX_TOTAL_RECENT_ENTRIES) {
files.length = HistoryMainService.MAX_TOTAL_RECENT_ENTRIES; files.length = HistoryMainService.MAX_TOTAL_RECENT_ENTRIES;
} }
@@ -143,7 +162,7 @@ export class HistoryMainService implements IHistoryMainService {
// Fill in files // Fill in files
for (let i = 0, entries = 0; i < mru.files.length && entries < HistoryMainService.MAX_MACOS_DOCK_RECENT_FILES; i++) { for (let i = 0, entries = 0; i < mru.files.length && entries < HistoryMainService.MAX_MACOS_DOCK_RECENT_FILES; i++) {
const loc = location(mru.files[i]); const loc = location(mru.files[i]);
if (loc.scheme === Schemas.file) { if (loc.scheme === Schemas.file && HistoryMainService.COMMON_FILES_FILTER.indexOf(basename(loc)) === -1) {
const filePath = originalFSPath(loc); const filePath = originalFSPath(loc);
if (await exists(filePath)) { if (await exists(filePath)) {
app.addRecentDocument(filePath); app.addRecentDocument(filePath);
@@ -162,7 +181,6 @@ export class HistoryMainService implements IHistoryMainService {
} }
getRecentlyOpened(currentWorkspace?: IWorkspaceIdentifier, currentFolder?: ISingleFolderWorkspaceIdentifier, currentFiles?: IPath[]): IRecentlyOpened { getRecentlyOpened(currentWorkspace?: IWorkspaceIdentifier, currentFolder?: ISingleFolderWorkspaceIdentifier, currentFiles?: IPath[]): IRecentlyOpened {
const workspaces: Array<IRecentFolder | IRecentWorkspace> = []; const workspaces: Array<IRecentFolder | IRecentWorkspace> = [];
const files: IRecentFile[] = []; const files: IRecentFile[] = [];
@@ -170,6 +188,7 @@ export class HistoryMainService implements IHistoryMainService {
if (currentWorkspace && !this.workspacesMainService.isUntitledWorkspace(currentWorkspace)) { if (currentWorkspace && !this.workspacesMainService.isUntitledWorkspace(currentWorkspace)) {
workspaces.push({ workspace: currentWorkspace }); workspaces.push({ workspace: currentWorkspace });
} }
if (currentFolder) { if (currentFolder) {
workspaces.push({ folderUri: currentFolder }); workspaces.push({ folderUri: currentFolder });
} }
@@ -183,12 +202,14 @@ export class HistoryMainService implements IHistoryMainService {
} }
} }
} }
this.addEntriesFromStorage(workspaces, files); this.addEntriesFromStorage(workspaces, files);
return { workspaces, files }; return { workspaces, files };
} }
private addEntriesFromStorage(workspaces: Array<IRecentFolder | IRecentWorkspace>, files: IRecentFile[]) { private addEntriesFromStorage(workspaces: Array<IRecentFolder | IRecentWorkspace>, files: IRecentFile[]) {
// Get from storage // Get from storage
let recents = this.getRecentlyOpenedFromStorage(); let recents = this.getRecentlyOpenedFromStorage();
for (let recent of recents.workspaces) { for (let recent of recents.workspaces) {
@@ -199,6 +220,7 @@ export class HistoryMainService implements IHistoryMainService {
workspaces.push(recent); workspaces.push(recent);
} }
} }
for (let recent of recents.files) { for (let recent of recents.files) {
let index = indexOfFile(files, recent.fileUri); let index = indexOfFile(files, recent.fileUri);
if (index >= 0) { if (index >= 0) {
@@ -211,11 +233,13 @@ export class HistoryMainService implements IHistoryMainService {
private getRecentlyOpenedFromStorage(): IRecentlyOpened { private getRecentlyOpenedFromStorage(): IRecentlyOpened {
const storedRecents = this.stateService.getItem<RecentlyOpenedStorageData>(HistoryMainService.recentlyOpenedStorageKey); const storedRecents = this.stateService.getItem<RecentlyOpenedStorageData>(HistoryMainService.recentlyOpenedStorageKey);
return restoreRecentlyOpened(storedRecents); return restoreRecentlyOpened(storedRecents);
} }
private saveRecentlyOpened(recent: IRecentlyOpened): void { private saveRecentlyOpened(recent: IRecentlyOpened): void {
const serialized = toStoreData(recent); const serialized = toStoreData(recent);
this.stateService.setItem(HistoryMainService.recentlyOpenedStorageKey, serialized); this.stateService.setItem(HistoryMainService.recentlyOpenedStorageKey, serialized);
} }
@@ -268,16 +292,17 @@ export class HistoryMainService implements IHistoryMainService {
items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => { items: arrays.coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => {
const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri; const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri;
const title = recent.label || getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome); const title = recent.label || getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome);
let description; let description;
let args; let args;
if (isSingleFolderWorkspaceIdentifier(workspace)) { if (isSingleFolderWorkspaceIdentifier(workspace)) {
const parentFolder = dirname(workspace); description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService));
description = nls.localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(parentFolder, this.environmentService));
args = `--folder-uri "${workspace.toString()}"`; args = `--folder-uri "${workspace.toString()}"`;
} else { } else {
description = nls.localize('codeWorkspace', "Code Workspace"); description = nls.localize('codeWorkspace', "Code Workspace");
args = `--file-uri "${workspace.configPath.toString()}"`; args = `--file-uri "${workspace.configPath.toString()}"`;
} }
return <Electron.JumpListItem>{ return <Electron.JumpListItem>{
type: 'task', type: 'task',
title, title,
@@ -308,9 +333,11 @@ function location(recent: IRecent): URI {
if (isRecentFolder(recent)) { if (isRecentFolder(recent)) {
return recent.folderUri; return recent.folderUri;
} }
if (isRecentFile(recent)) { if (isRecentFile(recent)) {
return recent.fileUri; return recent.fileUri;
} }
return recent.workspace.configPath; return recent.workspace.configPath;
} }

View File

@@ -55,7 +55,7 @@ export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefine
result.workspaces.push({ workspace: { id: workspace['id'], configPath: URI.file(workspace['configPath']) } }); result.workspaces.push({ workspace: { id: workspace['id'], configPath: URI.file(workspace['configPath']) } });
} else if (workspace && typeof workspace['path'] === 'string' && typeof workspace['scheme'] === 'string') { } else if (workspace && typeof workspace['path'] === 'string' && typeof workspace['scheme'] === 'string') {
// added by 1.26-insiders // added by 1.26-insiders
result.workspaces.push({ folderUri: URI.revive(workspace) }); result.workspaces.push({ folderUri: URI.revive(<UriComponents>workspace) });
} }
} }
} }

View File

@@ -56,6 +56,7 @@ export interface IssueReporterData extends WindowData {
styles: IssueReporterStyles; styles: IssueReporterStyles;
enabledExtensions: IssueReporterExtensionData[]; enabledExtensions: IssueReporterExtensionData[];
issueType?: IssueType; issueType?: IssueType;
extensionId?: string;
} }
export interface ISettingSearchResult { export interface ISettingSearchResult {

View File

@@ -30,7 +30,8 @@ export const enum ProgressLocation {
Scm = 3, Scm = 3,
Extensions = 5, Extensions = 5,
Window = 10, Window = 10,
Notification = 15 Notification = 15,
Dialog = 20
} }
export interface IProgressOptions { export interface IProgressOptions {

View File

@@ -19,7 +19,6 @@ export interface IRemoteAgentEnvironment {
userHome: URI; userHome: URI;
extensions: IExtensionDescription[]; extensions: IExtensionDescription[];
os: OperatingSystem; os: OperatingSystem;
syncExtensions: boolean;
} }
export interface RemoteAgentConnectionContext { export interface RemoteAgentConnectionContext {

View File

@@ -22,31 +22,30 @@ export interface IFileChangeDto {
export class RemoteExtensionsFileSystemProvider extends Disposable implements IFileSystemProvider { export class RemoteExtensionsFileSystemProvider extends Disposable implements IFileSystemProvider {
private readonly _session: string; private readonly session: string = generateUuid();
private readonly _channel: IChannel;
private readonly _onDidChange = this._register(new Emitter<IFileChange[]>()); private readonly _onDidChange = this._register(new Emitter<IFileChange[]>());
readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChange.event; readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChange.event;
public capabilities: FileSystemProviderCapabilities;
private readonly _onDidChangeCapabilities = this._register(new Emitter<void>()); private readonly _onDidChangeCapabilities = this._register(new Emitter<void>());
readonly onDidChangeCapabilities: Event<void> = this._onDidChangeCapabilities.event; readonly onDidChangeCapabilities: Event<void> = this._onDidChangeCapabilities.event;
constructor(channel: IChannel, environment: Promise<IRemoteAgentEnvironment | null>) { private _capabilities: FileSystemProviderCapabilities;
get capabilities(): FileSystemProviderCapabilities { return this._capabilities; }
constructor(private readonly channel: IChannel, environment: Promise<IRemoteAgentEnvironment | null>) {
super(); super();
this._session = generateUuid();
this._channel = channel;
this.setCaseSensitive(true); this.setCaseSensitive(true);
environment.then(remoteAgentEnvironment => this.setCaseSensitive(!!(remoteAgentEnvironment && remoteAgentEnvironment.os === OperatingSystem.Linux))); environment.then(remoteAgentEnvironment => this.setCaseSensitive(!!(remoteAgentEnvironment && remoteAgentEnvironment.os === OperatingSystem.Linux)));
this._channel.listen<IFileChangeDto[]>('filechange', [this._session])((events) => { this.registerListeners();
this._onDidChange.fire(events.map(RemoteExtensionsFileSystemProvider._createFileChange));
});
} }
dispose(): void { private registerListeners(): void {
super.dispose(); this._register(this.channel.listen<IFileChangeDto[]>('filechange', [this.session])((events) => {
this._onDidChange.fire(events.map(event => ({ resource: URI.revive(event.resource), type: event.type })));
}));
} }
setCaseSensitive(isCaseSensitive: boolean) { setCaseSensitive(isCaseSensitive: boolean) {
@@ -54,58 +53,55 @@ export class RemoteExtensionsFileSystemProvider extends Disposable implements IF
FileSystemProviderCapabilities.FileReadWrite FileSystemProviderCapabilities.FileReadWrite
| FileSystemProviderCapabilities.FileFolderCopy | FileSystemProviderCapabilities.FileFolderCopy
); );
if (isCaseSensitive) { if (isCaseSensitive) {
capabilities |= FileSystemProviderCapabilities.PathCaseSensitive; capabilities |= FileSystemProviderCapabilities.PathCaseSensitive;
} }
this.capabilities = capabilities;
this._capabilities = capabilities;
this._onDidChangeCapabilities.fire(undefined); this._onDidChangeCapabilities.fire(undefined);
} }
watch(resource: URI, opts: IWatchOptions): IDisposable {
const req = Math.random();
this._channel.call('watch', [this._session, req, resource, opts]);
return toDisposable(() => {
this._channel.call('unwatch', [this._session, req]);
});
}
private static _createFileChange(dto: IFileChangeDto): IFileChange {
return { resource: URI.revive(dto.resource), type: dto.type };
}
// --- forwarding calls // --- forwarding calls
stat(resource: URI): Promise<IStat> { stat(resource: URI): Promise<IStat> {
return this._channel.call('stat', [resource]); return this.channel.call('stat', [resource]);
} }
async readFile(resource: URI): Promise<Uint8Array> { async readFile(resource: URI): Promise<Uint8Array> {
const buff = <VSBuffer>await this._channel.call('readFile', [resource]); const buff = <VSBuffer>await this.channel.call('readFile', [resource]);
return buff.buffer; return buff.buffer;
} }
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> { writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
const contents = VSBuffer.wrap(content); return this.channel.call('writeFile', [resource, VSBuffer.wrap(content), opts]);
return this._channel.call('writeFile', [resource, contents, opts]);
} }
delete(resource: URI, opts: FileDeleteOptions): Promise<void> { delete(resource: URI, opts: FileDeleteOptions): Promise<void> {
return this._channel.call('delete', [resource, opts]); return this.channel.call('delete', [resource, opts]);
} }
mkdir(resource: URI): Promise<void> { mkdir(resource: URI): Promise<void> {
return this._channel.call('mkdir', [resource]); return this.channel.call('mkdir', [resource]);
} }
readdir(resource: URI): Promise<[string, FileType][]> { readdir(resource: URI): Promise<[string, FileType][]> {
return this._channel.call('readdir', [resource]); return this.channel.call('readdir', [resource]);
} }
rename(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> { rename(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> {
return this._channel.call('rename', [resource, target, opts]); return this.channel.call('rename', [resource, target, opts]);
} }
copy(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> { copy(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> {
return this._channel.call('copy', [resource, target, opts]); return this.channel.call('copy', [resource, target, opts]);
}
watch(resource: URI, opts: IWatchOptions): IDisposable {
const req = Math.random();
this.channel.call('watch', [this.session, req, resource, opts]);
return toDisposable(() => this.channel.call('unwatch', [this.session, req]));
} }
} }

View File

@@ -3,69 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { binarySearch } from 'vs/base/common/arrays'; import { toDisposable } from 'vs/base/common/lifecycle';
import { globals } from 'vs/base/common/platform'; import { globals } from 'vs/base/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import BaseErrorTelemetry, { ErrorEvent } from '../common/errorTelemetry';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import * as Errors from 'vs/base/common/errors';
import { safeStringify } from 'vs/base/common/objects';
/* __GDPR__FRAGMENT__ export default class ErrorTelemetry extends BaseErrorTelemetry {
"ErrorEvent" : { protected installErrorListeners(): void {
"stack": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"message" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"filename" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"callstack": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"msg" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"file" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"line": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"column": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"uncaught_error_name": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"uncaught_error_msg": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"count": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
*/
interface ErrorEvent {
callstack: string;
msg?: string;
file?: string;
line?: number;
column?: number;
uncaught_error_name?: string;
uncaught_error_msg?: string;
count?: number;
}
namespace ErrorEvent {
export function compare(a: ErrorEvent, b: ErrorEvent) {
if (a.callstack < b.callstack) {
return -1;
} else if (a.callstack > b.callstack) {
return 1;
}
return 0;
}
}
export default class ErrorTelemetry {
public static ERROR_FLUSH_TIMEOUT: number = 5 * 1000;
private _telemetryService: ITelemetryService;
private _flushDelay: number;
private _flushHandle: any = -1;
private _buffer: ErrorEvent[] = [];
private _disposables: IDisposable[] = [];
constructor(telemetryService: ITelemetryService, flushDelay = ErrorTelemetry.ERROR_FLUSH_TIMEOUT) {
this._telemetryService = telemetryService;
this._flushDelay = flushDelay;
// (1) check for unexpected but handled errors
const unbind = Errors.errorHandler.addListener((err) => this._onErrorEvent(err));
this._disposables.push(toDisposable(unbind));
// (2) check for uncaught global errors
let oldOnError: Function; let oldOnError: Function;
let that = this; let that = this;
if (typeof globals.onerror === 'function') { if (typeof globals.onerror === 'function') {
@@ -84,37 +27,7 @@ export default class ErrorTelemetry {
})); }));
} }
dispose() {
clearTimeout(this._flushHandle);
this._flushBuffer();
this._disposables = dispose(this._disposables);
}
private _onErrorEvent(err: any): void {
if (!err) {
return;
}
// unwrap nested errors from loader
if (err.detail && err.detail.stack) {
err = err.detail;
}
// work around behavior in workerServer.ts that breaks up Error.stack
let callstack = Array.isArray(err.stack) ? err.stack.join('\n') : err.stack;
let msg = err.message ? err.message : safeStringify(err);
// errors without a stack are not useful telemetry
if (!callstack) {
return;
}
this._enqueue({ msg, callstack });
}
private _onUncaughtError(msg: string, file: string, line: number, column?: number, err?: any): void { private _onUncaughtError(msg: string, file: string, line: number, column?: number, err?: any): void {
let data: ErrorEvent = { let data: ErrorEvent = {
callstack: msg, callstack: msg,
msg, msg,
@@ -138,38 +51,4 @@ export default class ErrorTelemetry {
this._enqueue(data); this._enqueue(data);
} }
private _enqueue(e: ErrorEvent): void {
const idx = binarySearch(this._buffer, e, ErrorEvent.compare);
if (idx < 0) {
e.count = 1;
this._buffer.splice(~idx, 0, e);
} else {
if (!this._buffer[idx].count) {
this._buffer[idx].count = 0;
}
this._buffer[idx].count! += 1;
}
if (this._flushHandle === -1) {
this._flushHandle = setTimeout(() => {
this._flushBuffer();
this._flushHandle = -1;
}, this._flushDelay);
}
}
private _flushBuffer(): void {
for (let error of this._buffer) {
/* __GDPR__
"UnhandledError" : {
"${include}": [ "${ErrorEvent}" ]
}
*/
// {{SQL CARBON EDIT}}
//this._telemetryService.publicLog('UnhandledError', error, true);
}
this._buffer.length = 0;
}
} }

View File

@@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { binarySearch } from 'vs/base/common/arrays';
import * as Errors from 'vs/base/common/errors';
import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { safeStringify } from 'vs/base/common/objects';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
/* __GDPR__FRAGMENT__
"ErrorEvent" : {
"stack": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"message" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"filename" : { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" },
"callstack": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"msg" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"file" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"line": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"column": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"uncaught_error_name": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"uncaught_error_msg": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"count": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
*/
export interface ErrorEvent {
callstack: string;
msg?: string;
file?: string;
line?: number;
column?: number;
uncaught_error_name?: string;
uncaught_error_msg?: string;
count?: number;
}
export namespace ErrorEvent {
export function compare(a: ErrorEvent, b: ErrorEvent) {
if (a.callstack < b.callstack) {
return -1;
} else if (a.callstack > b.callstack) {
return 1;
}
return 0;
}
}
export default abstract class BaseErrorTelemetry {
public static ERROR_FLUSH_TIMEOUT: number = 5 * 1000;
private _telemetryService: ITelemetryService;
private _flushDelay: number;
private _flushHandle: any = -1;
private _buffer: ErrorEvent[] = [];
protected _disposables: IDisposable[] = [];
constructor(telemetryService: ITelemetryService, flushDelay = BaseErrorTelemetry.ERROR_FLUSH_TIMEOUT) {
this._telemetryService = telemetryService;
this._flushDelay = flushDelay;
// (1) check for unexpected but handled errors
const unbind = Errors.errorHandler.addListener((err) => this._onErrorEvent(err));
this._disposables.push(toDisposable(unbind));
// (2) install implementation-specific error listeners
this.installErrorListeners();
}
dispose() {
clearTimeout(this._flushHandle);
this._flushBuffer();
this._disposables = dispose(this._disposables);
}
protected installErrorListeners(): void {
// to override
}
private _onErrorEvent(err: any): void {
if (!err) {
return;
}
// unwrap nested errors from loader
if (err.detail && err.detail.stack) {
err = err.detail;
}
// work around behavior in workerServer.ts that breaks up Error.stack
let callstack = Array.isArray(err.stack) ? err.stack.join('\n') : err.stack;
let msg = err.message ? err.message : safeStringify(err);
// errors without a stack are not useful telemetry
if (!callstack) {
return;
}
this._enqueue({ msg, callstack });
}
protected _enqueue(e: ErrorEvent): void {
const idx = binarySearch(this._buffer, e, ErrorEvent.compare);
if (idx < 0) {
e.count = 1;
this._buffer.splice(~idx, 0, e);
} else {
if (!this._buffer[idx].count) {
this._buffer[idx].count = 0;
}
this._buffer[idx].count! += 1;
}
if (this._flushHandle === -1) {
this._flushHandle = setTimeout(() => {
this._flushBuffer();
this._flushHandle = -1;
}, this._flushDelay);
}
}
private _flushBuffer(): void {
for (let error of this._buffer) {
/* __GDPR__
"UnhandledError" : {
"${include}": [ "${ErrorEvent}" ]
}
*/
// {{SQL CARBON EDIT}}
// this._telemetryService.publicLog('UnhandledError', error, true);
}
this._buffer.length = 0;
}
}

View File

@@ -29,6 +29,8 @@ export interface ITelemetryService {
*/ */
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void>; publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void>;
setEnabled(value: boolean): void;
getTelemetryInfo(): Promise<ITelemetryInfo>; getTelemetryInfo(): Promise<ITelemetryInfo>;
isOptedIn: boolean; isOptedIn: boolean;

View File

@@ -31,6 +31,7 @@ export class TelemetryService implements ITelemetryService {
private _commonProperties: Promise<{ [name: string]: any; }>; private _commonProperties: Promise<{ [name: string]: any; }>;
private _piiPaths: string[]; private _piiPaths: string[];
private _userOptIn: boolean; private _userOptIn: boolean;
private _enabled: boolean;
private _disposables: IDisposable[] = []; private _disposables: IDisposable[] = [];
private _cleanupPatterns: RegExp[] = []; private _cleanupPatterns: RegExp[] = [];
@@ -43,6 +44,7 @@ export class TelemetryService implements ITelemetryService {
this._commonProperties = config.commonProperties || Promise.resolve({}); this._commonProperties = config.commonProperties || Promise.resolve({});
this._piiPaths = config.piiPaths || []; this._piiPaths = config.piiPaths || [];
this._userOptIn = true; this._userOptIn = true;
this._enabled = true;
// static cleanup pattern for: `file:///DANGEROUS/PATH/resources/app/Useful/Information` // static cleanup pattern for: `file:///DANGEROUS/PATH/resources/app/Useful/Information`
this._cleanupPatterns = [/file:\/\/\/.*?\/resources\/app\//gi]; this._cleanupPatterns = [/file:\/\/\/.*?\/resources\/app\//gi];
@@ -74,13 +76,17 @@ export class TelemetryService implements ITelemetryService {
} }
} }
setEnabled(value: boolean): void {
this._enabled = value;
}
private _updateUserOptIn(): void { private _updateUserOptIn(): void {
const config = this._configurationService.getValue<any>(TELEMETRY_SECTION_ID); const config = this._configurationService.getValue<any>(TELEMETRY_SECTION_ID);
this._userOptIn = config ? config.enableTelemetry : this._userOptIn; this._userOptIn = config ? config.enableTelemetry : this._userOptIn;
} }
get isOptedIn(): boolean { get isOptedIn(): boolean {
return this._userOptIn; return this._userOptIn && this._enabled;
} }
getTelemetryInfo(): Promise<ITelemetryInfo> { getTelemetryInfo(): Promise<ITelemetryInfo> {
@@ -100,7 +106,7 @@ export class TelemetryService implements ITelemetryService {
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<any> { publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<any> {
// don't send events when the user is optout // don't send events when the user is optout
if (!this._userOptIn) { if (!this.isOptedIn) {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }

View File

@@ -14,6 +14,7 @@ export const NullTelemetryService = new class implements ITelemetryService {
publicLog(eventName: string, data?: ITelemetryData) { publicLog(eventName: string, data?: ITelemetryData) {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
setEnabled() { }
isOptedIn: true; isOptedIn: true;
getTelemetryInfo(): Promise<ITelemetryInfo> { getTelemetryInfo(): Promise<ITelemetryInfo> {
return Promise.resolve({ return Promise.resolve({

View File

@@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from 'vs/base/common/errors';
import BaseErrorTelemetry from '../common/errorTelemetry';
export default class ErrorTelemetry extends BaseErrorTelemetry {
protected installErrorListeners(): void {
// Print a console message when rejection isn't handled within N seconds. For details:
// see https://nodejs.org/api/process.html#process_event_unhandledrejection
// and https://nodejs.org/api/process.html#process_event_rejectionhandled
const unhandledPromises: Promise<any>[] = [];
process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
unhandledPromises.push(promise);
setTimeout(() => {
const idx = unhandledPromises.indexOf(promise);
if (idx >= 0) {
promise.catch(e => {
unhandledPromises.splice(idx, 1);
console.warn(`rejected promise not handled within 1 second: ${e}`);
if (e.stack) {
console.warn(`stack trace: ${e.stack}`);
}
onUnexpectedError(reason);
});
}
}, 1000);
});
process.on('rejectionHandled', (promise: Promise<any>) => {
const idx = unhandledPromises.indexOf(promise);
if (idx >= 0) {
unhandledPromises.splice(idx, 1);
}
});
// Print a console message when an exception isn't handled.
process.on('uncaughtException', (err: Error) => {
onUnexpectedError(err);
});
}
}

View File

@@ -16,6 +16,8 @@ import * as json from 'vs/base/common/json';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { normalizeDriveLetter } from 'vs/base/common/labels'; import { normalizeDriveLetter } from 'vs/base/common/labels';
import { toSlashes } from 'vs/base/common/extpath'; import { toSlashes } from 'vs/base/common/extpath';
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService'); export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService'); export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
@@ -75,6 +77,7 @@ export interface IResolvedWorkspace extends IWorkspaceIdentifier {
export interface IStoredWorkspace { export interface IStoredWorkspace {
folders: IStoredWorkspaceFolder[]; folders: IStoredWorkspaceFolder[];
remoteAuthority?: string;
} }
export interface IWorkspaceSavedEvent { export interface IWorkspaceSavedEvent {
@@ -232,12 +235,15 @@ export function rewriteWorkspaceFileForNewLocation(rawWorkspaceContents: string,
// Preserve as much of the existing workspace as possible by using jsonEdit // Preserve as much of the existing workspace as possible by using jsonEdit
// and only changing the folders portion. // and only changing the folders portion.
let newRawWorkspaceContents = rawWorkspaceContents; const formattingOptions: FormattingOptions = { insertSpaces: false, tabSize: 4, eol: (isLinux || isMacintosh) ? '\n' : '\r\n' };
const edits = jsonEdit.setProperty(rawWorkspaceContents, ['folders'], rewrittenFolders, { insertSpaces: false, tabSize: 4, eol: (isLinux || isMacintosh) ? '\n' : '\r\n' }); const edits = jsonEdit.setProperty(rawWorkspaceContents, ['folders'], rewrittenFolders, formattingOptions);
edits.forEach(edit => { let newContent = jsonEdit.applyEdits(rawWorkspaceContents, edits);
newRawWorkspaceContents = jsonEdit.applyEdit(rawWorkspaceContents, edit);
}); if (storedWorkspace.remoteAuthority === getRemoteAuthority(targetConfigPathURI)) {
return newRawWorkspaceContents; // unsaved remote workspaces have the remoteAuthority set. Remove it when no longer nexessary.
newContent = jsonEdit.applyEdits(newContent, jsonEdit.removeProperty(newContent, ['remoteAuthority'], formattingOptions));
}
return newContent;
} }
function doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace { function doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace {

5
src/vs/vscode.d.ts vendored
View File

@@ -5973,6 +5973,11 @@ declare module 'vscode' {
*/ */
export const appRoot: string; export const appRoot: string;
/**
* The custom uri scheme the editor registers to in the operating system.
*/
export const uriScheme: string;
/** /**
* Represents the preferred user-language, like `de-CH`, `fr`, or `en-US`. * Represents the preferred user-language, like `de-CH`, `fr`, or `en-US`.
*/ */

View File

@@ -616,11 +616,6 @@ declare module 'vscode' {
* An [event](#Event) that fires when the log level has changed. * An [event](#Event) that fires when the log level has changed.
*/ */
export const onDidChangeLogLevel: Event<LogLevel>; export const onDidChangeLogLevel: Event<LogLevel>;
/**
* The custom uri scheme the editor registers to in the operating system, like 'vscode', 'vscode-insiders'.
*/
export const uriScheme: string;
} }
//#endregion //#endregion

View File

@@ -112,7 +112,7 @@ export class MainThreadDecorations implements MainThreadDecorationsShape {
const provider = this._provider.get(handle); const provider = this._provider.get(handle);
if (provider) { if (provider) {
const [emitter] = provider; const [emitter] = provider;
emitter.fire(resources && resources.map(URI.revive)); emitter.fire(resources && resources.map(r => URI.revive(r)));
} }
} }

View File

@@ -162,7 +162,7 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
}); });
} else { } else {
searchOp.addMatch({ searchOp.addMatch({
resource: URI.revive(result) resource: URI.revive(<UriComponents>result)
}); });
} }
}); });

View File

@@ -47,7 +47,7 @@ export class OpenFolderAPICommand {
arg = { forceNewWindow: arg }; arg = { forceNewWindow: arg };
} }
if (!uri) { if (!uri) {
return executor.executeCommand('_files.pickFolderAndOpen', arg.forceNewWindow); return executor.executeCommand('_files.pickFolderAndOpen', { forceNewWindow: arg.forceNewWindow });
} }
const options: IOpenSettings = { forceNewWindow: arg.forceNewWindow, noRecentEntry: arg.noRecentEntry }; const options: IOpenSettings = { forceNewWindow: arg.forceNewWindow, noRecentEntry: arg.noRecentEntry };
uri = URI.revive(uri); uri = URI.revive(uri);
@@ -144,6 +144,13 @@ export class RemoveFromRecentlyOpenedAPICommand {
} }
CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute)); CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute));
export class OpenIssueReporter {
public static ID = 'vscode.openIssueReporter';
public static execute(executor: ICommandsExecutor, extensionId: string): Promise<void> {
return executor.executeCommand('workbench.action.openIssueReporter', [extensionId]);
}
}
interface RecentEntry { interface RecentEntry {
uri: URI; uri: URI;
type: 'workspace' | 'folder' | 'file'; type: 'workspace' | 'folder' | 'file';

View File

@@ -35,16 +35,17 @@ const configurationEntrySchema: IJSONSchema = {
properties: { properties: {
isExecutable: { isExecutable: {
type: 'boolean', type: 'boolean',
deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `application` value.' deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `machine` value.'
}, },
scope: { scope: {
type: 'string', type: 'string',
enum: ['application', 'window', 'resource'], enum: ['application', 'machine', 'window', 'resource'],
default: 'window', default: 'window',
enumDescriptions: [ enumDescriptions: [
nls.localize('scope.application.description', "Application specific configuration, which can be configured only in User settings."), nls.localize('scope.application.description', "Application specific configuration, which can be configured only in local user settings."),
nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."), nls.localize('scope.machine.description', "Machine specific configuration, which can be configured only in local and remote user settings."),
nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.") nls.localize('scope.window.description', "Window specific configuration, which can be configured in the user or workspace settings."),
nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the user, workspace or folder settings.")
], ],
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.") description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.")
}, },
@@ -161,7 +162,7 @@ configurationExtPoint.setHandler((extensions, { added, removed }) => {
validateProperties(configuration, extension); validateProperties(configuration, extension);
configuration.id = node.id || extension.description.identifier.value; configuration.id = node.id || extension.description.identifier.value;
configuration.contributedByExtension = true; configuration.extensionInfo = { id: extension.description.identifier.value };
configuration.title = configuration.title || extension.description.displayName || extension.description.identifier.value; configuration.title = configuration.title || extension.description.displayName || extension.description.identifier.value;
configurations.push(configuration); configurations.push(configuration);
return configurations; return configurations;
@@ -210,6 +211,8 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten
if (propertyConfiguration.scope) { if (propertyConfiguration.scope) {
if (propertyConfiguration.scope.toString() === 'application') { if (propertyConfiguration.scope.toString() === 'application') {
propertyConfiguration.scope = ConfigurationScope.APPLICATION; propertyConfiguration.scope = ConfigurationScope.APPLICATION;
} else if (propertyConfiguration.scope.toString() === 'machine') {
propertyConfiguration.scope = ConfigurationScope.MACHINE;
} else if (propertyConfiguration.scope.toString() === 'resource') { } else if (propertyConfiguration.scope.toString() === 'resource') {
propertyConfiguration.scope = ConfigurationScope.RESOURCE; propertyConfiguration.scope = ConfigurationScope.RESOURCE;
} else { } else {

View File

@@ -15,7 +15,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { CustomCodeAction } from 'vs/workbench/api/common/extHostLanguageFeatures'; import { CustomCodeAction } from 'vs/workbench/api/common/extHostLanguageFeatures';
import { ICommandsExecutor, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand } from './apiCommands'; import { ICommandsExecutor, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand, OpenIssueReporter } from './apiCommands';
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
import { isFalsyOrEmpty } from 'vs/base/common/arrays'; import { isFalsyOrEmpty } from 'vs/base/common/arrays';
@@ -258,6 +258,13 @@ export class ExtHostApiCommands {
{ name: 'layout', description: 'The editor layout to set.', constraint: (value: EditorGroupLayout) => typeof value === 'object' && Array.isArray(value.groups) } { name: 'layout', description: 'The editor layout to set.', constraint: (value: EditorGroupLayout) => typeof value === 'object' && Array.isArray(value.groups) }
] ]
}); });
this._register(OpenIssueReporter.ID, adjustHandler(OpenIssueReporter.execute), {
description: 'Opens the issue reporter with the provided extension id as the selected source',
args: [
{ name: 'extensionId', description: 'extensionId to report an issue on', constraint: (value: any) => typeof value === 'string' }
]
});
} }
// --- command impl // --- command impl

View File

@@ -17,7 +17,7 @@ export class ExtHostDialogs {
showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[] | undefined> { showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[] | undefined> {
return this._proxy.$showOpenDialog(options).then(filepaths => { return this._proxy.$showOpenDialog(options).then(filepaths => {
return filepaths ? filepaths.map(URI.revive) : undefined; return filepaths ? filepaths.map(p => URI.revive(p)) : undefined;
}); });
} }

View File

@@ -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 { IDisposable } from 'vs/base/common/lifecycle';
import { IExtensionMemento } from 'vs/workbench/api/common/extHostExtensionActivator';
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
export class ExtensionMemento implements IExtensionMemento {
private readonly _id: string;
private readonly _shared: boolean;
private readonly _storage: ExtHostStorage;
private readonly _init: Promise<ExtensionMemento>;
private _value: { [n: string]: any; };
private readonly _storageListener: IDisposable;
constructor(id: string, global: boolean, storage: ExtHostStorage) {
this._id = id;
this._shared = global;
this._storage = storage;
this._init = this._storage.getValue(this._shared, this._id, Object.create(null)).then(value => {
this._value = value;
return this;
});
this._storageListener = this._storage.onDidChangeStorage(e => {
if (e.shared === this._shared && e.key === this._id) {
this._value = e.value;
}
});
}
get whenReady(): Promise<ExtensionMemento> {
return this._init;
}
get<T>(key: string, defaultValue: T): T {
let value = this._value[key];
if (typeof value === 'undefined') {
value = defaultValue;
}
return value;
}
update(key: string, value: any): Promise<boolean> {
this._value[key] = value;
return this._storage
.setValue(this._shared, this._id, this._value)
.then(() => true);
}
dispose(): void {
this._storageListener.dispose();
}
}

View File

@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel { export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
@@ -35,7 +36,7 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
append(value: string): void { append(value: string): void {
this.validate(); this.validate();
this._offset += value ? Buffer.from(value).byteLength : 0; this._offset += value ? VSBuffer.fromString(value).byteLength : 0;
} }
update(): void { update(): void {

View File

@@ -478,8 +478,8 @@ export namespace WorkspaceEdit {
); );
} else { } else {
result.renameFile( result.renameFile(
URI.revive((<ResourceFileEditDto>edit).oldUri), URI.revive((<ResourceFileEditDto>edit).oldUri!),
URI.revive((<ResourceFileEditDto>edit).newUri), URI.revive((<ResourceFileEditDto>edit).newUri!),
(<ResourceFileEditDto>edit).options (<ResourceFileEditDto>edit).options
); );
} }

View File

@@ -420,7 +420,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
} }
return this._proxy.$startFileSearch(includePattern, includeFolder, excludePatternOrDisregardExcludes, maxResults, token) return this._proxy.$startFileSearch(includePattern, includeFolder, excludePatternOrDisregardExcludes, maxResults, token)
.then(data => Array.isArray(data) ? data.map(URI.revive) : []); .then(data => Array.isArray(data) ? data.map(d => URI.revive(d)) : []);
} }
findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.TextSearchComplete | undefined> { findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.TextSearchComplete | undefined> {

View File

@@ -414,7 +414,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
function reviveWebviewOptions(options: WebviewInputOptions): WebviewInputOptions { function reviveWebviewOptions(options: WebviewInputOptions): WebviewInputOptions {
return { return {
...options, ...options,
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(URI.revive) : undefined, localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(r => URI.revive(r)) : undefined,
}; };
} }

View File

@@ -3,11 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors'; import * as errors from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { TernarySearchTree } from 'vs/base/common/map';
import * as path from 'vs/base/common/path'; import * as path from 'vs/base/common/path';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
@@ -16,7 +14,7 @@ import { OverviewRulerLane } from 'vs/editor/common/model';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration'; import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { score } from 'vs/editor/common/modes/languageSelector'; import { score } from 'vs/editor/common/modes/languageSelector';
import * as files from 'vs/platform/files/common/files'; import * as files from 'vs/platform/files/common/files';
import { ExtHostContext, IInitData, IMainContext, MainContext, MainThreadKeytarShape, IEnvironment, MainThreadWindowShape, MainThreadTelemetryShape } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostContext, IInitData, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands'; import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard'; import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
@@ -47,7 +45,7 @@ import { LogOutputChannelFactory } from 'vs/workbench/api/node/extHostOutputServ
import { ExtHostProgress } from 'vs/workbench/api/common/extHostProgress'; import { ExtHostProgress } from 'vs/workbench/api/common/extHostProgress';
import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen'; import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen';
import { ExtHostSCM } from 'vs/workbench/api/common/extHostSCM'; import { ExtHostSCM } from 'vs/workbench/api/common/extHostSCM';
import { ExtHostSearch } from 'vs/workbench/api/node/extHostSearch'; import { ExtHostSearch, registerEHSearchProviders } from 'vs/workbench/api/node/extHostSearch';
import { ExtHostStatusBar } from 'vs/workbench/api/common/extHostStatusBar'; import { ExtHostStatusBar } from 'vs/workbench/api/common/extHostStatusBar';
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
@@ -60,7 +58,7 @@ import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview'; import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow'; import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { throwProposedApiError, checkProposedApiEnabled, nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
@@ -69,7 +67,7 @@ import { originalFSPath } from 'vs/base/common/resources';
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer'; import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
import { withNullAsUndefined } from 'vs/base/common/types'; import { withNullAsUndefined } from 'vs/base/common/types';
import { values } from 'vs/base/common/collections'; import { values } from 'vs/base/common/collections';
import { endsWith } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network';
export interface IExtensionApiFactory { export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -93,11 +91,11 @@ export function createApiFactory(
extHostConfiguration: ExtHostConfiguration, extHostConfiguration: ExtHostConfiguration,
extensionService: ExtHostExtensionService, extensionService: ExtHostExtensionService,
extHostLogService: ExtHostLogService, extHostLogService: ExtHostLogService,
extHostStorage: ExtHostStorage extHostStorage: ExtHostStorage,
schemeTransformer: ISchemeTransformer | null,
outputChannelName: string
): IExtensionApiFactory { ): IExtensionApiFactory {
const schemeTransformer: ISchemeTransformer | null = null;
// Addressable instances // Addressable instances
rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService); rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService);
const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService()); const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
@@ -131,6 +129,14 @@ export function createApiFactory(
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(LogOutputChannelFactory, initData.logsLocation, rpcProtocol)); const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(LogOutputChannelFactory, initData.logsLocation, rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage); rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
if (initData.remoteAuthority) { if (initData.remoteAuthority) {
extHostTask.registerTaskSystem(Schemas.vscodeRemote, {
scheme: Schemas.vscodeRemote,
authority: initData.remoteAuthority,
platform: process.platform
});
registerEHSearchProviders(extHostSearch, extHostLogService);
const cliServer = new CLIServer(extHostCommands); const cliServer = new CLIServer(extHostCommands);
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath; process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
} }
@@ -147,8 +153,7 @@ export function createApiFactory(
const extHostLanguages = new ExtHostLanguages(rpcProtocol, extHostDocuments); const extHostLanguages = new ExtHostLanguages(rpcProtocol, extHostDocuments);
// Register an output channel for exthost log // Register an output channel for exthost log
const name = localize('extensionsLog', "Extension Host"); extHostOutputService.createOutputChannelFromLogFile(outputChannelName, extHostLogService.logFile);
extHostOutputService.createOutputChannelFromLogFile(name, extHostLogService.logFile);
// Register API-ish commands // Register API-ish commands
ExtHostApiCommands.register(extHostCommands); ExtHostApiCommands.register(extHostCommands);
@@ -881,240 +886,3 @@ class Extension<T> implements vscode.Extension<T> {
return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports); return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports);
} }
} }
interface LoadFunction {
(request: string, parent: { filename: string; }, isMain: any): any;
}
interface INodeModuleFactory {
readonly nodeModuleName: string | string[];
load(request: string, parent: { filename: string; }, isMain: any, original: LoadFunction): any;
alternaiveModuleName?(name: string): string | undefined;
}
export class NodeModuleRequireInterceptor {
public static INSTANCE = new NodeModuleRequireInterceptor();
private readonly _factories: Map<string, INodeModuleFactory>;
private readonly _alternatives: ((moduleName: string) => string | undefined)[];
constructor() {
this._factories = new Map<string, INodeModuleFactory>();
this._alternatives = [];
this._installInterceptor(this._factories, this._alternatives);
}
private _installInterceptor(factories: Map<string, INodeModuleFactory>, alternatives: ((moduleName: string) => string | undefined)[]): void {
const node_module = <any>require.__$__nodeRequire('module');
const original = node_module._load;
node_module._load = function load(request: string, parent: { filename: string; }, isMain: any) {
for (let alternativeModuleName of alternatives) {
let alternative = alternativeModuleName(request);
if (alternative) {
request = alternative;
break;
}
}
if (!factories.has(request)) {
return original.apply(this, arguments);
}
return factories.get(request)!.load(request, parent, isMain, original);
};
}
public register(interceptor: INodeModuleFactory): void {
if (Array.isArray(interceptor.nodeModuleName)) {
for (let moduleName of interceptor.nodeModuleName) {
this._factories.set(moduleName, interceptor);
}
} else {
this._factories.set(interceptor.nodeModuleName, interceptor);
}
if (typeof interceptor.alternaiveModuleName === 'function') {
this._alternatives.push((moduleName) => {
return interceptor.alternaiveModuleName!(moduleName);
});
}
}
}
export class VSCodeNodeModuleFactory implements INodeModuleFactory {
public readonly nodeModuleName = 'vscode';
private readonly _extApiImpl = new Map<string, typeof vscode>();
private _defaultApiImpl: typeof vscode;
constructor(
private readonly _apiFactory: IExtensionApiFactory,
private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>,
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
private readonly _configProvider: ExtHostConfigProvider
) {
}
public load(request: string, parent: { filename: string; }): any {
// get extension id from filename and api for extension
const ext = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
if (ext) {
let apiImpl = this._extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
if (!apiImpl) {
apiImpl = this._apiFactory(ext, this._extensionRegistry, this._configProvider);
this._extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
}
return apiImpl;
}
// fall back to a default implementation
if (!this._defaultApiImpl) {
let extensionPathsPretty = '';
this._extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
this._defaultApiImpl = this._apiFactory(nullExtensionDescription, this._extensionRegistry, this._configProvider);
}
return this._defaultApiImpl;
}
}
interface IKeytarModule {
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
}
export class KeytarNodeModuleFactory implements INodeModuleFactory {
public readonly nodeModuleName: string = 'keytar';
private alternativeNames: Set<string> | undefined;
private _impl: IKeytarModule;
constructor(mainThreadKeytar: MainThreadKeytarShape, environment: IEnvironment) {
if (environment.appRoot) {
let appRoot = environment.appRoot.fsPath;
if (process.platform === 'win32') {
appRoot = appRoot.replace(/\\/g, '/');
}
if (appRoot[appRoot.length - 1] === '/') {
appRoot = appRoot.substr(0, appRoot.length - 1);
}
this.alternativeNames = new Set();
this.alternativeNames.add(`${appRoot}/node_modules.asar/keytar`);
this.alternativeNames.add(`${appRoot}/node_modules/keytar`);
}
this._impl = {
getPassword: (service: string, account: string): Promise<string | null> => {
return mainThreadKeytar.$getPassword(service, account);
},
setPassword: (service: string, account: string, password: string): Promise<void> => {
return mainThreadKeytar.$setPassword(service, account, password);
},
deletePassword: (service: string, account: string): Promise<boolean> => {
return mainThreadKeytar.$deletePassword(service, account);
},
findPassword: (service: string): Promise<string | null> => {
return mainThreadKeytar.$findPassword(service);
}
};
}
public load(request: string, parent: { filename: string; }): any {
return this._impl;
}
public alternaiveModuleName(name: string): string | undefined {
const length = name.length;
// We need at least something like: `?/keytar` which requires
// more than 7 characters.
if (length <= 7 || !this.alternativeNames) {
return undefined;
}
const sep = length - 7;
if ((name.charAt(sep) === '/' || name.charAt(sep) === '\\') && endsWith(name, 'keytar')) {
name = name.replace(/\\/g, '/');
if (this.alternativeNames.has(name)) {
return 'keytar';
}
}
return undefined;
}
}
interface OpenOptions {
wait: boolean;
app: string | string[];
}
interface IOriginalOpen {
(target: string, options?: OpenOptions): Thenable<any>;
}
interface IOpenModule {
(target: string, options?: OpenOptions): Thenable<void>;
}
export class OpenNodeModuleFactory implements INodeModuleFactory {
public readonly nodeModuleName: string[] = ['open', 'opn'];
private _extensionId: string | undefined;
private _original: IOriginalOpen;
private _impl: IOpenModule;
constructor(mainThreadWindow: MainThreadWindowShape, private _mainThreadTelemerty: MainThreadTelemetryShape, private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>) {
this._impl = (target, options) => {
const uri: URI = URI.parse(target);
// If we have options use the original method.
if (options) {
return this.callOriginal(target, options);
}
if (uri.scheme === 'http' || uri.scheme === 'https') {
return mainThreadWindow.$openUri(uri);
} else if (uri.scheme === 'mailto') {
return mainThreadWindow.$openUri(uri);
}
return this.callOriginal(target, options);
};
}
public load(request: string, parent: { filename: string; }, isMain: any, original: LoadFunction): any {
// get extension id from filename and api for extension
const extension = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
if (extension) {
this._extensionId = extension.identifier.value;
this.sendShimmingTelemetry();
}
this._original = original(request, parent, isMain);
return this._impl;
}
private callOriginal(target: string, options: OpenOptions | undefined): Thenable<any> {
this.sendNoForwardTelemetry();
return this._original(target, options);
}
private sendShimmingTelemetry(): void {
if (!this._extensionId) {
return;
}
/* __GDPR__
"shimming.open" : {
"extension": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._mainThreadTelemerty.$publicLog('shimming.open', { extension: this._extensionId });
}
private sendNoForwardTelemetry(): void {
if (!this._extensionId) {
return;
}
/* __GDPR__
"shimming.open.call.noForward" : {
"extension": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._mainThreadTelemerty.$publicLog('shimming.open.call.noForward', { extension: this._extensionId });
}
}

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