Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)

This commit is contained in:
Anthony Dresser
2019-08-12 21:31:51 -07:00
committed by GitHub
parent 00250839fc
commit 7eba8c4c03
616 changed files with 9472 additions and 7087 deletions

5
.vscode/tasks.json vendored
View File

@@ -81,6 +81,7 @@
"type": "gulp", "type": "gulp",
"task": "hygiene", "task": "hygiene",
"problemMatcher": [] "problemMatcher": []
} },
] ]
} }

View File

@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron" disturl "https://atom.io/download/electron"
target "4.2.7" target "4.2.9"
runtime "electron" runtime "electron"

View File

@@ -2,11 +2,12 @@ steps:
- script: | - script: |
mkdir -p .build mkdir -p .build
echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $BUILD_SOURCEVERSION > .build/commit
echo -n $VSCODE_QUALITY > .build/quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e
echo 'noop'

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e
echo 'noop'

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e
echo 'noop'

View File

@@ -2,11 +2,12 @@ steps:
- script: | - script: |
mkdir -p .build mkdir -p .build
echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $BUILD_SOURCEVERSION > .build/commit
echo -n $VSCODE_QUALITY > .build/quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true
@@ -112,4 +113,4 @@ steps:
- 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'
continueOnError: true continueOnError: true

View File

@@ -2,11 +2,12 @@ steps:
- script: | - script: |
mkdir -p .build mkdir -p .build
echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $BUILD_SOURCEVERSION > .build/commit
echo -n $VSCODE_QUALITY > .build/quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true

View File

@@ -66,6 +66,17 @@ jobs:
steps: steps:
- template: linux/product-build-linux-multiarch.yml - template: linux/product-build-linux-multiarch.yml
- job: LinuxArm64
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ARM64'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
pool:
vmImage: 'Ubuntu-16.04'
variables:
VSCODE_ARCH: arm64
dependsOn:
- Compile
steps:
- template: linux/product-build-linux-multiarch.yml
- job: LinuxAlpine - job: LinuxAlpine
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable')) condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_LINUX_ALPINE'], 'true'), ne(variables['VSCODE_QUALITY'], 'stable'))
pool: pool:
@@ -128,6 +139,9 @@ jobs:
steps: steps:
- template: sync-mooncake.yml - template: sync-mooncake.yml
trigger: none
pr: none
schedules: schedules:
- cron: "0 5 * * Mon-Fri" - cron: "0 5 * * Mon-Fri"
displayName: Mon-Fri at 7:00 displayName: Mon-Fri at 7:00

View File

@@ -2,11 +2,12 @@ steps:
- script: | - script: |
mkdir -p .build mkdir -p .build
echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $BUILD_SOURCEVERSION > .build/commit
echo -n $VSCODE_QUALITY > .build/quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true
@@ -116,9 +117,9 @@ steps:
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true
alias: 'Compilation' alias: 'Compilation'
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true')) condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))

View File

@@ -13,19 +13,37 @@ const util = require('../lib/util');
const root = path.dirname(path.dirname(__dirname)); const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root); const commit = util.getVersion(root);
function main() { // optionally allow to pass in explicit base/maps to upload
const vs = vfs.src('out-vscode-min/**/*.map', { base: 'out-vscode-min' }) // client source-maps only const [, , base, maps] = process.argv;
const fetch = function (base, maps = `${base}/**/*.map`) {
return vfs.src(maps, { base })
.pipe(es.mapSync(f => { .pipe(es.mapSync(f => {
f.path = `${f.base}/core/${f.relative}`; f.path = `${f.base}/core/${f.relative}`;
return f; return f;
})); }));
};
const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' }); function main() {
const sources = [];
return es.merge(vs, extensionsOut) // vscode client maps (default)
if (!base) {
const vs = fetch('out-vscode-min'); // client source-maps only
sources.push(vs);
const extensionsOut = vfs.src(['.build/extensions/**/*.js.map', '!**/node_modules/**'], { base: '.build' });
sources.push(extensionsOut);
}
// specific client base/maps
else {
sources.push(fetch(base, maps));
}
return es.merge(...sources)
.pipe(es.through(function (data) { .pipe(es.through(function (data) {
// debug console.log('Uploading Sourcemap', data.relative); // debug
console.log('Uploading Sourcemap', data.relative);
this.emit('data', data); this.emit('data', data);
})) }))
.pipe(azure.upload({ .pipe(azure.upload({
@@ -36,4 +54,4 @@ function main() {
})); }));
} }
main(); main();

View File

@@ -2,11 +2,12 @@ steps:
- script: | - script: |
mkdir -p .build mkdir -p .build
echo -n $BUILD_SOURCEVERSION > .build/commit echo -n $BUILD_SOURCEVERSION > .build/commit
echo -n $VSCODE_QUALITY > .build/quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true
@@ -87,6 +88,15 @@ steps:
yarn gulp vscode-web-min-ci yarn gulp vscode-web-min-ci
displayName: Build displayName: Build
# upload only the workbench.web.api.js source maps because
# we just compiled these bits in the previous step and the
# general task to upload source maps has already been run
- script: |
set -e
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.api.js.map
displayName: Upload sourcemaps (Web)
- script: | - script: |
set -e set -e
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \

View File

@@ -2,11 +2,12 @@ steps:
- powershell: | - powershell: |
mkdir .build -ea 0 mkdir .build -ea 0
"$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit "$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit
"$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality
displayName: Prepare cache flag displayName: Prepare cache flag
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1 - task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs: inputs:
keyfile: 'build/.cachesalt, .build/commit' keyfile: 'build/.cachesalt, .build/commit, .build/quality'
targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min' targetfolder: '.build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min'
vstsFeed: 'npm-vscode' vstsFeed: 'npm-vscode'
platformIndependent: true platformIndependent: true

View File

@@ -31,6 +31,7 @@ const BUILD_TARGETS = [
{ platform: 'linux', arch: 'ia32', pkgTarget: 'node8-linux-x86' }, { platform: 'linux', arch: 'ia32', pkgTarget: 'node8-linux-x86' },
{ platform: 'linux', arch: 'x64', pkgTarget: 'node8-linux-x64' }, { platform: 'linux', arch: 'x64', pkgTarget: 'node8-linux-x64' },
{ platform: 'linux', arch: 'armhf', pkgTarget: 'node8-linux-armv7' }, { platform: 'linux', arch: 'armhf', pkgTarget: 'node8-linux-armv7' },
{ platform: 'linux', arch: 'arm64', pkgTarget: 'node8-linux-arm64' },
{ platform: 'linux', arch: 'alpine', pkgTarget: 'node8-linux-alpine' }, { platform: 'linux', arch: 'alpine', pkgTarget: 'node8-linux-alpine' },
]; ];
@@ -41,6 +42,7 @@ gulp.task('vscode-reh-win32-x64-min', noop);
gulp.task('vscode-reh-darwin-min', noop); gulp.task('vscode-reh-darwin-min', noop);
gulp.task('vscode-reh-linux-x64-min', noop); gulp.task('vscode-reh-linux-x64-min', noop);
gulp.task('vscode-reh-linux-armhf-min', noop); gulp.task('vscode-reh-linux-armhf-min', noop);
gulp.task('vscode-reh-linux-arm64-min', noop);
gulp.task('vscode-reh-linux-alpine-min', noop); gulp.task('vscode-reh-linux-alpine-min', noop);
gulp.task('vscode-reh-web-win32-ia32-min', noop); gulp.task('vscode-reh-web-win32-ia32-min', noop);

View File

@@ -58,7 +58,7 @@ const nodeModules = [
// Build // Build
const vscodeEntryPoints = _.flatten([ const vscodeEntryPoints = _.flatten([
buildfile.entrypoint('vs/workbench/workbench.main'), buildfile.entrypoint('vs/workbench/workbench.desktop.main'),
buildfile.base, buildfile.base,
buildfile.serviceWorker, buildfile.serviceWorker,
buildfile.workbench, buildfile.workbench,
@@ -255,8 +255,8 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const out = sourceFolderName; const out = sourceFolderName;
const checksums = computeChecksums(out, [ const checksums = computeChecksums(out, [
'vs/workbench/workbench.main.js', 'vs/workbench/workbench.desktop.main.js',
'vs/workbench/workbench.main.css', 'vs/workbench/workbench.desktop.main.css',
'vs/code/electron-browser/workbench/workbench.html', 'vs/code/electron-browser/workbench/workbench.html',
'vs/code/electron-browser/workbench/workbench.js' 'vs/code/electron-browser/workbench/workbench.js'
]); ]);
@@ -353,7 +353,15 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(electron(_.extend({}, config, { platform, arch, ffmpegChromium: true }))) .pipe(electron(_.extend({}, config, { platform, arch, ffmpegChromium: true })))
.pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version'], { dot: true })); .pipe(filter(['**', '!LICENSE', '!LICENSES.chromium.html', '!version'], { dot: true }));
// result = es.merge(result, gulp.src('resources/completions/**', { base: '.' })); if (platform === 'linux') {
result = es.merge(result, gulp.src('resources/completions/bash/code', { base: '.' })
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(function (f) { f.basename = product.applicationName; })));
result = es.merge(result, gulp.src('resources/completions/zsh/_code', { base: '.' })
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename(function (f) { f.basename = '_' + product.applicationName; })));
}
if (platform === 'win32') { if (platform === 'win32') {
result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32', allowEmpty: true })); result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32', allowEmpty: true }));

View File

@@ -55,11 +55,13 @@ function prepareDebPackage(arch) {
const icon = gulp.src('resources/linux/code.png', { base: '.' }) const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename('usr/share/pixmaps/' + product.linuxIconName + '.png')); .pipe(rename('usr/share/pixmaps/' + product.linuxIconName + '.png'));
// const bash_completion = gulp.src('resources/completions/bash/code') const bash_completion = gulp.src('resources/completions/bash/code')
// .pipe(rename('usr/share/bash-completion/completions/code')); .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('usr/share/bash-completion/completions/' + product.applicationName));
// const zsh_completion = gulp.src('resources/completions/zsh/_code') const zsh_completion = gulp.src('resources/completions/zsh/_code')
// .pipe(rename('usr/share/zsh/vendor-completions/_code')); .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('usr/share/zsh/vendor-completions/_' + product.applicationName));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; })); .pipe(rename(function (p) { p.dirname = 'usr/share/' + product.applicationName + '/' + p.dirname; }));
@@ -95,7 +97,7 @@ function prepareDebPackage(arch) {
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
.pipe(rename('DEBIAN/postinst')); .pipe(rename('DEBIAN/postinst'));
const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, icon, /* bash_completion, zsh_completion, */ code); const all = es.merge(control, postinst, postrm, prerm, desktops, appdata, icon, bash_completion, zsh_completion, code);
return all.pipe(vfs.dest(destination)); return all.pipe(vfs.dest(destination));
}; };
@@ -146,11 +148,13 @@ function prepareRpmPackage(arch) {
const icon = gulp.src('resources/linux/code.png', { base: '.' }) const icon = gulp.src('resources/linux/code.png', { base: '.' })
.pipe(rename('BUILD/usr/share/pixmaps/' + product.linuxIconName + '.png')); .pipe(rename('BUILD/usr/share/pixmaps/' + product.linuxIconName + '.png'));
// const bash_completion = gulp.src('resources/completions/bash/code') const bash_completion = gulp.src('resources/completions/bash/code')
// .pipe(rename('BUILD/usr/share/bash-completion/completions/code')); .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('BUILD/usr/share/bash-completion/completions/' + product.applicationName));
// const zsh_completion = gulp.src('resources/completions/zsh/_code') const zsh_completion = gulp.src('resources/completions/zsh/_code')
// .pipe(rename('BUILD/usr/share/zsh/site-functions/_code')); .pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(rename('BUILD/usr/share/zsh/site-functions/_' + product.applicationName));
const code = gulp.src(binaryDir + '/**/*', { base: binaryDir }) const code = gulp.src(binaryDir + '/**/*', { base: binaryDir })
.pipe(rename(function (p) { p.dirname = 'BUILD/usr/share/' + product.applicationName + '/' + p.dirname; })); .pipe(rename(function (p) { p.dirname = 'BUILD/usr/share/' + product.applicationName + '/' + p.dirname; }));
@@ -173,7 +177,7 @@ function prepareRpmPackage(arch) {
const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' }) const specIcon = gulp.src('resources/linux/rpm/code.xpm', { base: '.' })
.pipe(rename('SOURCES/' + product.applicationName + '.xpm')); .pipe(rename('SOURCES/' + product.applicationName + '.xpm'));
const all = es.merge(code, desktops, appdata, icon, /* bash_completion, zsh_completion, */ spec, specIcon); const all = es.merge(code, desktops, appdata, icon, bash_completion, zsh_completion, spec, specIcon);
return all.pipe(vfs.dest(getRpmBuildPath(rpmArch))); return all.pipe(vfs.dest(getRpmBuildPath(rpmArch)));
}; };

View File

@@ -29,12 +29,18 @@ const commit = util.getVersion(root);
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
function fromLocal(extensionPath) { function fromLocal(extensionPath) {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js'); const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
if (fs.existsSync(webpackFilename)) { const input = fs.existsSync(webpackFilename)
return fromLocalWebpack(extensionPath); ? fromLocalWebpack(extensionPath)
} : fromLocalNormal(extensionPath);
else { const tmLanguageJsonFilter = filter('**/*.tmLanguage.json', { restore: true });
return fromLocalNormal(extensionPath); return input
} .pipe(tmLanguageJsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f) => {
f.contents = Buffer.from(JSON.stringify(JSON.parse(f.contents.toString('utf8'))));
return f;
}))
.pipe(tmLanguageJsonFilter.restore);
} }
function fromLocalWebpack(extensionPath) { function fromLocalWebpack(extensionPath) {
const result = es.through(); const result = es.through();

View File

@@ -30,11 +30,20 @@ const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${
function fromLocal(extensionPath: string): Stream { function fromLocal(extensionPath: string): Stream {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js'); const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
if (fs.existsSync(webpackFilename)) { const input = fs.existsSync(webpackFilename)
return fromLocalWebpack(extensionPath); ? fromLocalWebpack(extensionPath)
} else { : fromLocalNormal(extensionPath);
return fromLocalNormal(extensionPath);
} const tmLanguageJsonFilter = filter('**/*.tmLanguage.json', { restore: true });
return input
.pipe(tmLanguageJsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f: File) => {
f.contents = Buffer.from(JSON.stringify(JSON.parse(f.contents.toString('utf8'))));
return f;
}))
.pipe(tmLanguageJsonFilter.restore);
} }
function fromLocalWebpack(extensionPath: string): Stream { function fromLocalWebpack(extensionPath: string): Stream {

View File

@@ -269,6 +269,10 @@
{ {
"name": "vs/workbench/services/preferences", "name": "vs/workbench/services/preferences",
"project": "vscode-preferences" "project": "vscode-preferences"
},
{
"name": "vs/workbench/services/notification",
"project": "vscode-workbench"
} }
] ]
} }

View File

@@ -78,4 +78,42 @@ const processTreeDts = path.join('node_modules', 'windows-process-tree', 'typing
if (fs.existsSync(processTreeDts)) { if (fs.existsSync(processTreeDts)) {
console.log('Removing windows-process-tree.d.ts'); console.log('Removing windows-process-tree.d.ts');
fs.unlinkSync(processTreeDts); fs.unlinkSync(processTreeDts);
} }
function getInstalledVersion(packageName, cwd) {
const opts = {};
if (cwd) {
opts.cwd = cwd;
}
const result = cp.spawnSync(yarn, ['list', '--pattern', packageName], opts);
const stdout = result.stdout.toString();
const match = stdout.match(new RegExp(packageName + '@(\\S+)'));
if (!match || !match[1]) {
throw new Error('Unexpected output from yarn list: ' + stdout);
}
return match[1];
}
function assertSameVersionsBetweenFolders(packageName, otherFolder) {
const baseVersion = getInstalledVersion(packageName);
const otherVersion = getInstalledVersion(packageName, otherFolder);
if (baseVersion !== otherVersion) {
throw new Error(`Mismatched versions installed for ${packageName}: root has ${baseVersion}, ./${otherFolder} has ${otherVersion}. These should be the same!`);
}
}
// Check that modules in both the base package.json and remote/ have the same version installed
const requireSameVersionsInRemote = [
'xterm',
'xterm-addon-search',
'xterm-addon-web-links',
'node-pty',
'vscode-ripgrep'
];
requireSameVersionsInRemote.forEach(packageName => {
assertSameVersionsBetweenFolders(packageName, 'remote');
});

View File

@@ -132,7 +132,7 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'mas
if (packageJsonPathOverride) { if (packageJsonPathOverride) {
packageJsonPath += packageJsonPathOverride; packageJsonPath += packageJsonPathOverride;
} }
packageJsonPath += '/package.json'; packageJsonPath += 'package.json';
for (let i = 0; i < cgmanifestRead.registrations.length; i++) { for (let i = 0; i < cgmanifestRead.registrations.length; i++) {
if (cgmanifestRead.registrations[i].component.git.repositoryUrl.substr(cgmanifestRead.registrations[i].component.git.repositoryUrl.length - repoId.length, repoId.length) === repoId) { if (cgmanifestRead.registrations[i].component.git.repositoryUrl.substr(cgmanifestRead.registrations[i].component.git.repositoryUrl.length - repoId.length, repoId.length) === repoId) {
cgmanifestRead.registrations[i].component.git.commitHash = info.commitSha; cgmanifestRead.registrations[i].component.git.commitHash = info.commitSha;

View File

@@ -44,7 +44,7 @@
"service-downloader": "github:anthonydresser/service-downloader#0.1.5", "service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"typescript": "3.5.2", "typescript": "3.5.2",
"vsce": "1.48.0", "vsce": "1.48.0",
"vscode-telemetry-extractor": "1.5.3", "vscode-telemetry-extractor": "^1.5.4",
"xml2js": "^0.4.17" "xml2js": "^0.4.17"
}, },
"scripts": { "scripts": {

View File

@@ -3618,19 +3618,19 @@ vsce@1.48.0:
yauzl "^2.3.1" yauzl "^2.3.1"
yazl "^2.2.2" yazl "^2.2.2"
vscode-ripgrep@^1.5.5: vscode-ripgrep@^1.5.6:
version "1.5.5" version "1.5.6"
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.5.tgz#24c0e9cb356cf889c98e15ecb58f9cf654a1d961" resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.6.tgz#93bf5c99ca5f8248950a305e224f6ca153c30af4"
integrity sha512-OrPrAmcun4+uZAuNcQvE6CCPskh+5AsjANod/Q3zRcJcGNxgoOSGlQN9RPtatkUNmkN8Nn8mZBnS1jMylu/dKg== integrity sha512-WRIM9XpUj6dsfdAmuI3ANbmT1ysPUVsYy/2uCLDHJa9kbiB4T7uGvFnnc0Rgx2qQnyRAwL7PeWaFgUljPPxf2g==
vscode-telemetry-extractor@1.5.3: vscode-telemetry-extractor@^1.5.4:
version "1.5.3" version "1.5.4"
resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.5.3.tgz#c17f9065a47425edafd23ea161e80c23274e009d" resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.5.4.tgz#bcb0d17667fa1b77715e3a3bf372ade18f846782"
integrity sha512-feioJ1e1KyMa9rzblnLbSOduo+Ny0l62H3/bSDgfgCSnU/km+tTSYxPBvZHVr7iQfQGC95J61yC/ObqS9EbaQg== integrity sha512-MN9LNPo0Rc6cy3sIWTAG97PTWkEKdRnP0VeYoS8vjKSNtG9CAsrUxHgFfYoHm2vNK/ijd0a4NzETyVGO2kT6hw==
dependencies: dependencies:
command-line-args "^5.1.1" command-line-args "^5.1.1"
ts-morph "^3.1.3" ts-morph "^3.1.3"
vscode-ripgrep "^1.5.5" vscode-ripgrep "^1.5.6"
vso-node-api@6.1.2-preview: vso-node-api@6.1.2-preview:
version "6.1.2-preview" version "6.1.2-preview"

View File

@@ -60,12 +60,12 @@
"git": { "git": {
"name": "electron", "name": "electron",
"repositoryUrl": "https://github.com/electron/electron", "repositoryUrl": "https://github.com/electron/electron",
"commitHash": "36ea114ac0616e469e75ae94e6d53af48925e036" "commitHash": "3d4d6454007f14fa9a5f0e1fa49206fb91b676cc"
} }
}, },
"isOnlyProductionDependency": true, "isOnlyProductionDependency": true,
"license": "MIT", "license": "MIT",
"version": "4.2.7" "version": "4.2.9"
}, },
{ {
"component": { "component": {

View File

@@ -1148,6 +1148,26 @@
"description": "%config.enableSmartCommit%", "description": "%config.enableSmartCommit%",
"default": false "default": false
}, },
"git.smartCommitChanges": {
"type": "string",
"enum": [
"all",
"tracked"
],
"enumDescriptions": [
"%config.smartCommitChanges.all%",
"%config.smartCommitChanges.tracked%"
],
"scope": "resource",
"description": "%config.smartCommitChanges%",
"default": "all"
},
"git.suggestSmartCommit": {
"type": "boolean",
"scope": "resource",
"description": "%config.suggestSmartCommit%",
"default": true
},
"git.enableCommitSigning": { "git.enableCommitSigning": {
"type": "boolean", "type": "boolean",
"scope": "resource", "scope": "resource",
@@ -1165,10 +1185,26 @@
"default": true, "default": true,
"description": "%config.decorations.enabled%" "description": "%config.decorations.enabled%"
}, },
"git.promptToSaveFilesBeforeCommit": { "git.enableStatusBarSync": {
"type": "boolean", "type": "boolean",
"scope": "resource",
"default": true, "default": true,
"description": "%config.enableStatusBarSync%",
"scope": "resource"
},
"git.promptToSaveFilesBeforeCommit": {
"type": "string",
"enum": [
"always",
"staged",
"never"
],
"enumDescriptions": [
"%config.promptToSaveFilesBeforeCommit.always%",
"%config.promptToSaveFilesBeforeCommit.staged%",
"%config.promptToSaveFilesBeforeCommit.never%"
],
"scope": "resource",
"default": "always",
"description": "%config.promptToSaveFilesBeforeCommit%" "description": "%config.promptToSaveFilesBeforeCommit%"
}, },
"git.postCommitCommand": { "git.postCommitCommand": {
@@ -1312,6 +1348,12 @@
"scope": "resource", "scope": "resource",
"default": true, "default": true,
"description": "%config.openDiffOnClick%" "description": "%config.openDiffOnClick%"
},
"git.supportCancellation": {
"type": "boolean",
"scope": "resource",
"default": false,
"description": "%config.supportCancellation%"
} }
} }
}, },
@@ -1477,4 +1519,4 @@
"@types/which": "^1.0.28", "@types/which": "^1.0.28",
"mocha": "^3.2.0" "mocha": "^3.2.0"
} }
} }

View File

@@ -89,10 +89,18 @@
"config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.", "config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.",
"config.defaultCloneDirectory": "The default location to clone a git repository.", "config.defaultCloneDirectory": "The default location to clone a git repository.",
"config.enableSmartCommit": "Commit all changes when there are no staged changes.", "config.enableSmartCommit": "Commit all changes when there are no staged changes.",
"config.smartCommitChanges": "Control which changes are automatically staged by Smart Commit.",
"config.smartCommitChanges.all": "Automatically stage all changes.",
"config.smartCommitChanges.tracked": "Automatically staged tracked changes only.",
"config.suggestSmartCommit": "Suggests to enable smart commit (commit all changes when there are no staged changes).",
"config.enableCommitSigning": "Enables commit signing with GPG.", "config.enableCommitSigning": "Enables commit signing with GPG.",
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.", "config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.",
"config.decorations.enabled": "Controls whether Git contributes colors and badges to the explorer and the open editors view.", "config.decorations.enabled": "Controls whether Git contributes colors and badges to the explorer and the open editors view.",
"config.enableStatusBarSync": "Controls whether the Git Sync command appears in the status bar.",
"config.promptToSaveFilesBeforeCommit": "Controls whether Git should check for unsaved files before committing.", "config.promptToSaveFilesBeforeCommit": "Controls whether Git should check for unsaved files before committing.",
"config.promptToSaveFilesBeforeCommit.always": "Check for any unsaved files.",
"config.promptToSaveFilesBeforeCommit.staged": "Check only for unsaved staged files.",
"config.promptToSaveFilesBeforeCommit.never": "Disable this check.",
"config.postCommitCommand": "Runs a git command after a successful commit.", "config.postCommitCommand": "Runs a git command after a successful commit.",
"config.postCommitCommand.none": "Don't run any command after a commit.", "config.postCommitCommand.none": "Don't run any command after a commit.",
"config.postCommitCommand.push": "Run 'Git Push' after a successful commit.", "config.postCommitCommand.push": "Run 'Git Push' after a successful commit.",
@@ -118,6 +126,7 @@
"config.useForcePushWithLease": "Controls whether force pushing uses the safer force-with-lease variant.", "config.useForcePushWithLease": "Controls whether force pushing uses the safer force-with-lease variant.",
"config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.", "config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.",
"config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.", "config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.",
"config.supportCancellation": "Controls whether a notification comes up when running the Sync action, which allows the user to cancel the operation.",
"colors.added": "Color for added resources.", "colors.added": "Color for added resources.",
"colors.modified": "Color for modified resources.", "colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.", "colors.deleted": "Color for deleted resources.",
@@ -125,4 +134,4 @@
"colors.ignored": "Color for ignored resources.", "colors.ignored": "Color for ignored resources.",
"colors.conflict": "Color for resources with conflicts.", "colors.conflict": "Color for resources with conflicts.",
"colors.submodule": "Color for submodule resources." "colors.submodule": "Color for submodule resources."
} }

View File

@@ -238,5 +238,6 @@ export const enum GitErrorCodes {
CantLockRef = 'CantLockRef', CantLockRef = 'CantLockRef',
CantRebaseMultipleBranches = 'CantRebaseMultipleBranches', CantRebaseMultipleBranches = 'CantRebaseMultipleBranches',
PatchDoesNotApply = 'PatchDoesNotApply', PatchDoesNotApply = 'PatchDoesNotApply',
NoPathFound = 'NoPathFound' NoPathFound = 'NoPathFound',
UnknownPath = 'UnknownPath',
} }

View File

@@ -353,9 +353,11 @@ export class CommandCenter {
switch (resource.type) { switch (resource.type) {
case Status.INDEX_MODIFIED: case Status.INDEX_MODIFIED:
case Status.INDEX_RENAMED: case Status.INDEX_RENAMED:
case Status.INDEX_ADDED:
return this.getURI(resource.original, 'HEAD'); return this.getURI(resource.original, 'HEAD');
case Status.MODIFIED: case Status.MODIFIED:
case Status.UNTRACKED:
return this.getURI(resource.resourceUri, '~'); return this.getURI(resource.resourceUri, '~');
case Status.DELETED_BY_THEM: case Status.DELETED_BY_THEM:
@@ -414,6 +416,7 @@ export class CommandCenter {
switch (resource.type) { switch (resource.type) {
case Status.INDEX_MODIFIED: case Status.INDEX_MODIFIED:
case Status.INDEX_RENAMED: case Status.INDEX_RENAMED:
case Status.INDEX_ADDED:
return `${basename} (Index)`; return `${basename} (Index)`;
case Status.MODIFIED: case Status.MODIFIED:
@@ -426,6 +429,10 @@ export class CommandCenter {
case Status.DELETED_BY_THEM: case Status.DELETED_BY_THEM:
return `${basename} (Ours)`; return `${basename} (Ours)`;
case Status.UNTRACKED:
return `${basename} (Untracked)`;
} }
return ''; return '';
@@ -450,6 +457,8 @@ export class CommandCenter {
return; return;
} }
url = url.trim().replace(/^git\s+clone\s+/, '');
const config = workspace.getConfiguration('git'); const config = workspace.getConfiguration('git');
let defaultCloneDirectory = config.get<string>('defaultCloneDirectory') || os.homedir(); let defaultCloneDirectory = config.get<string>('defaultCloneDirectory') || os.homedir();
defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir()); defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir());
@@ -698,7 +707,13 @@ export class CommandCenter {
viewColumn: ViewColumn.Active viewColumn: ViewColumn.Active
}; };
const document = await workspace.openTextDocument(uri); let document;
try {
document = await workspace.openTextDocument(uri);
} catch (error) {
await commands.executeCommand<void>('vscode.open', uri, opts);
continue;
}
// Check if active text editor has same path as other editor. we cannot compare via // Check if active text editor has same path as other editor. we cannot compare via
// URI.toString() here because the schemas can be different. Instead we just go by path. // URI.toString() here because the schemas can be different. Instead we just go by path.
@@ -1225,23 +1240,35 @@ export class CommandCenter {
opts?: CommitOptions opts?: CommitOptions
): Promise<boolean> { ): Promise<boolean> {
const config = workspace.getConfiguration('git', Uri.file(repository.root)); const config = workspace.getConfiguration('git', Uri.file(repository.root));
const promptToSaveFilesBeforeCommit = config.get<boolean>('promptToSaveFilesBeforeCommit') === true; let promptToSaveFilesBeforeCommit = config.get<'always' | 'staged' | 'never'>('promptToSaveFilesBeforeCommit');
if (promptToSaveFilesBeforeCommit) { // migration
const unsavedTextDocuments = workspace.textDocuments if (promptToSaveFilesBeforeCommit as any === true) {
promptToSaveFilesBeforeCommit = 'always';
} else if (promptToSaveFilesBeforeCommit as any === false) {
promptToSaveFilesBeforeCommit = 'never';
}
if (promptToSaveFilesBeforeCommit !== 'never') {
let documents = workspace.textDocuments
.filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath)); .filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath));
if (unsavedTextDocuments.length > 0) { if (promptToSaveFilesBeforeCommit === 'staged') {
const message = unsavedTextDocuments.length === 1 documents = documents
? localize('unsaved files single', "The following file is unsaved: {0}.\n\nWould you like to save it before committing?", path.basename(unsavedTextDocuments[0].uri.fsPath)) .filter(d => repository.indexGroup.resourceStates.some(s => s.resourceUri.path === d.uri.fsPath));
: localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before committing?", unsavedTextDocuments.length); }
if (documents.length > 0) {
const message = documents.length === 1
? localize('unsaved files single', "The following file is unsaved and will not be included in the commit if you proceed: {0}.\n\nWould you like to save it before committing?", path.basename(documents[0].uri.fsPath))
: localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before committing?", documents.length);
const saveAndCommit = localize('save and commit', "Save All & Commit"); const saveAndCommit = localize('save and commit', "Save All & Commit");
const commit = localize('commit', "Commit Anyway"); const commit = localize('commit', "Commit Anyway");
const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit); const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit);
if (pick === saveAndCommit) { if (pick === saveAndCommit) {
await Promise.all(unsavedTextDocuments.map(d => d.save())); await Promise.all(documents.map(d => d.save()));
await repository.status(); await repository.add(documents.map(d => d.uri));
} else if (pick !== commit) { } else if (pick !== commit) {
return false; // do not commit on cancel return false; // do not commit on cancel
} }
@@ -1255,15 +1282,24 @@ export class CommandCenter {
// no changes, and the user has not configured to commit all in this case // no changes, and the user has not configured to commit all in this case
if (!noUnstagedChanges && noStagedChanges && !enableSmartCommit) { if (!noUnstagedChanges && noStagedChanges && !enableSmartCommit) {
const suggestSmartCommit = config.get<boolean>('suggestSmartCommit') === true;
if (!suggestSmartCommit) {
return false;
}
// prompt the user if we want to commit all or not // prompt the user if we want to commit all or not
const message = localize('no staged changes', "There are no staged changes to commit.\n\nWould you like to automatically stage all your changes and commit them directly?"); const message = localize('no staged changes', "There are no staged changes to commit.\n\nWould you like to automatically stage all your changes and commit them directly?");
const yes = localize('yes', "Yes"); const yes = localize('yes', "Yes");
const always = localize('always', "Always"); const always = localize('always', "Always");
const pick = await window.showWarningMessage(message, { modal: true }, yes, always); const never = localize('never', "Never");
const pick = await window.showWarningMessage(message, { modal: true }, yes, always, never);
if (pick === always) { if (pick === always) {
config.update('enableSmartCommit', true, true); config.update('enableSmartCommit', true, true);
} else if (pick === never) {
config.update('suggestSmartCommit', false, true);
return false;
} else if (pick !== yes) { } else if (pick !== yes) {
return false; // do not commit on cancel return false; // do not commit on cancel
} }
@@ -1301,6 +1337,10 @@ export class CommandCenter {
return false; return false;
} }
if (opts.all && config.get<'all' | 'tracked'>('smartCommitChanges') === 'tracked') {
opts.all = 'tracked';
}
await repository.commit(message, opts); await repository.commit(message, opts);
const postCommitCommand = config.get<'none' | 'push' | 'sync'>('postCommitCommand'); const postCommitCommand = config.get<'none' | 'push' | 'sync'>('postCommitCommand');
@@ -1350,19 +1390,6 @@ export class CommandCenter {
await this.commitWithAnyInput(repository); await this.commitWithAnyInput(repository);
} }
@command('git.commitWithInput', { repository: true })
async commitWithInput(repository: Repository): Promise<void> {
if (!repository.inputBox.value) {
return;
}
const didCommit = await this.smartCommit(repository, async () => repository.inputBox.value);
if (didCommit) {
repository.inputBox.value = await repository.getCommitTemplate();
}
}
@command('git.commitStaged', { repository: true }) @command('git.commitStaged', { repository: true })
async commitStaged(repository: Repository): Promise<void> { async commitStaged(repository: Repository): Promise<void> {
await this.commitWithAnyInput(repository, { all: false }); await this.commitWithAnyInput(repository, { all: false });
@@ -1487,12 +1514,12 @@ export class CommandCenter {
await this._branch(repository, undefined, true); await this._branch(repository, undefined, true);
} }
private async _branch(repository: Repository, defaultName?: string, from = false): Promise<void> { private async promptForBranchName(defaultName?: string): Promise<string> {
const config = workspace.getConfiguration('git'); const config = workspace.getConfiguration('git');
const branchWhitespaceChar = config.get<string>('branchWhitespaceChar')!; const branchWhitespaceChar = config.get<string>('branchWhitespaceChar')!;
const branchValidationRegex = config.get<string>('branchValidationRegex')!; const branchValidationRegex = config.get<string>('branchValidationRegex')!;
const sanitize = (name: string) => name ? const sanitize = (name: string) => name ?
name.trim().replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, branchWhitespaceChar) name.trim().replace(/^-+/, '').replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, branchWhitespaceChar)
: name; : name;
const rawBranchName = defaultName || await window.showInputBox({ const rawBranchName = defaultName || await window.showInputBox({
@@ -1509,7 +1536,11 @@ export class CommandCenter {
} }
}); });
const branchName = sanitize(rawBranchName || ''); return sanitize(rawBranchName || '');
}
private async _branch(repository: Repository, defaultName?: string, from = false): Promise<void> {
const branchName = await this.promptForBranchName(defaultName);
if (!branchName) { if (!branchName) {
return; return;
@@ -1571,25 +1602,21 @@ export class CommandCenter {
@command('git.renameBranch', { repository: true }) @command('git.renameBranch', { repository: true })
async renameBranch(repository: Repository): Promise<void> { async renameBranch(repository: Repository): Promise<void> {
const name = await window.showInputBox({ const branchName = await this.promptForBranchName();
placeHolder: localize('branch name', "Branch name"),
prompt: localize('provide branch name', "Please provide a branch name"),
value: repository.HEAD && repository.HEAD.name
});
if (!name || name.trim().length === 0) { if (!branchName) {
return; return;
} }
try { try {
await repository.renameBranch(name); await repository.renameBranch(branchName);
} catch (err) { } catch (err) {
switch (err.gitErrorCode) { switch (err.gitErrorCode) {
case GitErrorCodes.InvalidBranchName: case GitErrorCodes.InvalidBranchName:
window.showErrorMessage(localize('invalid branch name', 'Invalid branch name')); window.showErrorMessage(localize('invalid branch name', 'Invalid branch name'));
return; return;
case GitErrorCodes.BranchAlreadyExists: case GitErrorCodes.BranchAlreadyExists:
window.showErrorMessage(localize('branch already exists', "A branch named '{0}' already exists", name)); window.showErrorMessage(localize('branch already exists', "A branch named '{0}' already exists", branchName));
return; return;
default: default:
throw err; throw err;
@@ -1913,7 +1940,17 @@ export class CommandCenter {
private async _sync(repository: Repository, rebase: boolean): Promise<void> { private async _sync(repository: Repository, rebase: boolean): Promise<void> {
const HEAD = repository.HEAD; const HEAD = repository.HEAD;
if (!HEAD || !HEAD.upstream) { if (!HEAD) {
return;
} else if (!HEAD.upstream) {
const branchName = HEAD.name;
const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName);
const yes = localize('ok', "OK");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick === yes) {
await this.publish(repository);
}
return; return;
} }
@@ -1945,8 +1982,16 @@ export class CommandCenter {
} }
@command('git.sync', { repository: true }) @command('git.sync', { repository: true })
sync(repository: Repository): Promise<void> { async sync(repository: Repository): Promise<void> {
return this._sync(repository, false); try {
await this._sync(repository, false);
} catch (err) {
if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) {
return;
}
throw err;
}
} }
@command('git._syncAll') @command('git._syncAll')
@@ -1963,8 +2008,16 @@ export class CommandCenter {
} }
@command('git.syncRebase', { repository: true }) @command('git.syncRebase', { repository: true })
syncRebase(repository: Repository): Promise<void> { async syncRebase(repository: Repository): Promise<void> {
return this._sync(repository, true); try {
await this._sync(repository, true);
} catch (err) {
if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) {
return;
}
throw err;
}
} }
@command('git.publish', { repository: true }) @command('git.publish', { repository: true })

View File

@@ -11,12 +11,15 @@ import * as which from 'which';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import iconv = require('iconv-lite'); import iconv = require('iconv-lite');
import * as filetype from 'file-type'; import * as filetype from 'file-type';
import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent } from './util'; import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
import { CancellationToken } from 'vscode'; import { CancellationToken } from 'vscode';
import { URI } from 'vscode-uri'; import { URI } from 'vscode-uri';
import { detectEncoding } from './encoding'; import { detectEncoding } from './encoding';
import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status } from './api/git'; import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status } from './api/git';
// https://github.com/microsoft/vscode/issues/65693
const MAX_CLI_LENGTH = 30000;
const readfile = denodeify<string, string | null, string>(fs.readFile); const readfile = denodeify<string, string | null, string>(fs.readFile);
export interface IGit { export interface IGit {
@@ -339,7 +342,7 @@ export class Git {
} }
async clone(url: string, parentPath: string, cancellationToken?: CancellationToken): Promise<string> { async clone(url: string, parentPath: string, cancellationToken?: CancellationToken): Promise<string> {
let baseFolderName = decodeURI(url).replace(/[\/]+$/, '').replace(/^.*\//, '').replace(/\.git$/, '') || 'repository'; let baseFolderName = decodeURI(url).replace(/[\/]+$/, '').replace(/^.*[\/\\]/, '').replace(/\.git$/, '') || 'repository';
let folderName = baseFolderName; let folderName = baseFolderName;
let folderPath = path.join(parentPath, folderName); let folderPath = path.join(parentPath, folderName);
let count = 1; let count = 1;
@@ -598,13 +601,13 @@ export function parseGitmodules(raw: string): Submodule[] {
} }
export function parseGitCommit(raw: string): Commit | null { export function parseGitCommit(raw: string): Commit | null {
const match = /^([0-9a-f]{40})\n(.*)\n(.*)\n([^]*)$/m.exec(raw.trim()); const match = /^([0-9a-f]{40})\n(.*)\n(.*)(\n([^]*))?$/m.exec(raw.trim());
if (!match) { if (!match) {
return null; return null;
} }
const parents = match[3] ? match[3].split(' ') : []; const parents = match[3] ? match[3].split(' ') : [];
return { hash: match[1], message: match[4], parents, authorEmail: match[2] }; return { hash: match[1], message: match[5], parents, authorEmail: match[2] };
} }
interface LsTreeElement { interface LsTreeElement {
@@ -639,7 +642,7 @@ export function parseLsFiles(raw: string): LsFilesElement[] {
} }
export interface CommitOptions { export interface CommitOptions {
all?: boolean; all?: boolean | 'tracked';
amend?: boolean; amend?: boolean;
signoff?: boolean; signoff?: boolean;
signCommit?: boolean; signCommit?: boolean;
@@ -649,6 +652,7 @@ export interface CommitOptions {
export interface PullOptions { export interface PullOptions {
unshallow?: boolean; unshallow?: boolean;
tags?: boolean; tags?: boolean;
readonly cancellationToken?: CancellationToken;
} }
export enum ForcePushMode { export enum ForcePushMode {
@@ -797,7 +801,7 @@ export class Repository {
const elements = await this.lsfiles(path); const elements = await this.lsfiles(path);
if (elements.length === 0) { if (elements.length === 0) {
throw new GitError({ message: 'Error running ls-files' }); throw new GitError({ message: 'Path not known by git', gitErrorCode: GitErrorCodes.UnknownPath });
} }
const { mode, object } = elements[0]; const { mode, object } = elements[0];
@@ -810,7 +814,7 @@ export class Repository {
const elements = await this.lstree(treeish, path); const elements = await this.lstree(treeish, path);
if (elements.length === 0) { if (elements.length === 0) {
throw new GitError({ message: 'Error running ls-files' }); throw new GitError({ message: 'Path not known by git', gitErrorCode: GitErrorCodes.UnknownPath });
} }
const { mode, object, size } = elements[0]; const { mode, object, size } = elements[0];
@@ -1077,8 +1081,16 @@ export class Repository {
return result.stdout.trim(); return result.stdout.trim();
} }
async add(paths: string[]): Promise<void> { async add(paths: string[], opts?: { update?: boolean }): Promise<void> {
const args = ['add', '-A', '--']; const args = ['add'];
if (opts && opts.update) {
args.push('-u');
} else {
args.push('-A');
}
args.push('--');
if (paths && paths.length) { if (paths && paths.length) {
args.push.apply(args, paths); args.push.apply(args, paths);
@@ -1116,15 +1128,21 @@ export class Repository {
} }
let mode: string; let mode: string;
let add: string = '';
try { try {
const details = await this.getObjectDetails('HEAD', path); const details = await this.getObjectDetails('HEAD', path);
mode = details.mode; mode = details.mode;
} catch (err) { } catch (err) {
if (err.gitErrorCode !== GitErrorCodes.UnknownPath) {
throw err;
}
mode = '100644'; mode = '100644';
add = '--add';
} }
await this.run(['update-index', '--cacheinfo', mode, hash, path]); await this.run(['update-index', add, '--cacheinfo', mode, hash, path]);
} }
async checkout(treeish: string, paths: string[], opts: { track?: boolean } = Object.create(null)): Promise<void> { async checkout(treeish: string, paths: string[], opts: { track?: boolean } = Object.create(null)): Promise<void> {
@@ -1138,13 +1156,14 @@ export class Repository {
args.push(treeish); args.push(treeish);
} }
if (paths && paths.length) {
args.push('--');
args.push.apply(args, paths);
}
try { try {
await this.run(args); if (paths && paths.length > 0) {
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
await this.run([...args, '--', ...chunk]);
}
} else {
await this.run(args);
}
} catch (err) { } catch (err) {
if (/Please,? commit your changes or stash them/.test(err.stderr || '')) { if (/Please,? commit your changes or stash them/.test(err.stderr || '')) {
err.gitErrorCode = GitErrorCodes.DirtyWorkTree; err.gitErrorCode = GitErrorCodes.DirtyWorkTree;
@@ -1275,11 +1294,17 @@ export class Repository {
async clean(paths: string[]): Promise<void> { async clean(paths: string[]): Promise<void> {
const pathsByGroup = groupBy(paths, p => path.dirname(p)); const pathsByGroup = groupBy(paths, p => path.dirname(p));
const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]); const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]);
const tasks = groups.map(paths => () => this.run(['clean', '-f', '-q', '--'].concat(paths)));
for (let task of tasks) { const limiter = new Limiter(5);
await task(); const promises: Promise<any>[] = [];
for (const paths of groups) {
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
promises.push(limiter.queue(() => this.run(['clean', '-f', '-q', '--', ...chunk])));
}
} }
await Promise.all(promises);
} }
async undo(): Promise<void> { async undo(): Promise<void> {
@@ -1396,7 +1421,7 @@ export class Repository {
} }
try { try {
await this.run(args); await this.run(args, options);
} catch (err) { } catch (err) {
if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout || '')) { if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout || '')) {
err.gitErrorCode = GitErrorCodes.Conflict; err.gitErrorCode = GitErrorCodes.Conflict;
@@ -1669,13 +1694,16 @@ export class Repository {
async getBranch(name: string): Promise<Branch> { async getBranch(name: string): Promise<Branch> {
if (name === 'HEAD') { if (name === 'HEAD') {
return this.getHEAD(); return this.getHEAD();
} else if (/^@/.test(name)) {
const symbolicFullNameResult = await this.run(['rev-parse', '--symbolic-full-name', name]);
const symbolicFullName = symbolicFullNameResult.stdout.trim();
name = symbolicFullName || name;
} }
const result = await this.run(['rev-parse', name]); let result = await this.run(['rev-parse', name]);
if (!result.stdout && /^@/.test(name)) {
const symbolicFullNameResult = await this.run(['rev-parse', '--symbolic-full-name', name]);
name = symbolicFullNameResult.stdout.trim();
result = await this.run(['rev-parse', name]);
}
if (!result.stdout) { if (!result.stdout) {
return Promise.reject<Branch>(new Error('No such branch')); return Promise.reject<Branch>(new Error('No such branch'));
@@ -1732,7 +1760,7 @@ export class Repository {
} }
const raw = await readfile(templatePath, 'utf8'); const raw = await readfile(templatePath, 'utf8');
return raw.replace(/^\s*#.*$\n?/gm, '').trim(); return raw.replace(/\n?#.*/g, '');
} catch (err) { } catch (err) {
return ''; return '';
@@ -1745,8 +1773,11 @@ export class Repository {
} }
async updateSubmodules(paths: string[]): Promise<void> { async updateSubmodules(paths: string[]): Promise<void> {
const args = ['submodule', 'update', '--', ...paths]; const args = ['submodule', 'update', '--'];
await this.run(args);
for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) {
await this.run([...args, ...chunk]);
}
} }
async getSubmodules(): Promise<Submodule[]> { async getSubmodules(): Promise<Submodule[]> {

View File

@@ -3,9 +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 { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType, OutputChannel, LogLevel, env } from 'vscode'; import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType, OutputChannel, LogLevel, env, ProgressOptions, CancellationToken } from 'vscode';
import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git'; import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git';
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, combinedDisposable, watch, IFileWatcher } from './util'; import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, combinedDisposable } from './util';
import { memoize, throttle, debounce } from './decorators'; import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri'; import { toGitUri } from './uri';
import { AutoFetcher } from './autofetch'; import { AutoFetcher } from './autofetch';
@@ -14,6 +14,7 @@ import * as nls from 'vscode-nls';
import * as fs from 'fs'; import * as fs from 'fs';
import { StatusBarCommands } from './statusbar'; import { StatusBarCommands } from './statusbar';
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git'; import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git';
import { IFileWatcher, watch } from './watch';
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis)); const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
@@ -678,12 +679,15 @@ export class Repository implements Disposable {
const root = Uri.file(repository.root); const root = Uri.file(repository.root);
this._sourceControl = scm.createSourceControl('git', 'Git', root); this._sourceControl = scm.createSourceControl('git', 'Git', root);
this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)");
this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.acceptInputCommand = { command: 'git.commit', title: localize('commit', "Commit"), arguments: [this._sourceControl] };
this._sourceControl.quickDiffProvider = this; this._sourceControl.quickDiffProvider = this;
this._sourceControl.inputBox.validateInput = this.validateInput.bind(this); this._sourceControl.inputBox.validateInput = this.validateInput.bind(this);
this.disposables.push(this._sourceControl); this.disposables.push(this._sourceControl);
this.updateInputBoxPlaceholder();
this.disposables.push(this.onDidRunGitStatus(() => this.updateInputBoxPlaceholder()));
this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "MERGE CHANGES")); this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "MERGE CHANGES"));
this._indexGroup = this._sourceControl.createResourceGroup('index', localize('staged changes', "STAGED CHANGES")); this._indexGroup = this._sourceControl.createResourceGroup('index', localize('staged changes', "STAGED CHANGES"));
this._workingTreeGroup = this._sourceControl.createResourceGroup('workingTree', localize('changes', "CHANGES")); this._workingTreeGroup = this._sourceControl.createResourceGroup('workingTree', localize('changes', "CHANGES"));
@@ -723,6 +727,10 @@ export class Repository implements Disposable {
const progressManager = new ProgressManager(this); const progressManager = new ProgressManager(this);
this.disposables.push(progressManager); this.disposables.push(progressManager);
const onDidChangeCountBadge = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.countBadge', root));
onDidChangeCountBadge(this.setCountBadge, this, this.disposables);
this.setCountBadge();
this.updateCommitTemplate(); this.updateCommitTemplate();
} }
@@ -905,7 +913,8 @@ export class Repository implements Disposable {
if (this.rebaseCommit) { if (this.rebaseCommit) {
await this.run(Operation.RebaseContinue, async () => { await this.run(Operation.RebaseContinue, async () => {
if (opts.all) { if (opts.all) {
await this.repository.add([]); const addOpts = opts.all === 'tracked' ? { update: true } : {};
await this.repository.add([], addOpts);
} }
await this.repository.rebaseContinue(); await this.repository.rebaseContinue();
@@ -913,9 +922,11 @@ export class Repository implements Disposable {
} else { } else {
await this.run(Operation.Commit, async () => { await this.run(Operation.Commit, async () => {
if (opts.all) { if (opts.all) {
await this.repository.add([]); const addOpts = opts.all === 'tracked' ? { update: true } : {};
await this.repository.add([], addOpts);
} }
delete opts.all;
await this.repository.commit(message, opts); await this.repository.commit(message, opts);
}); });
} }
@@ -956,21 +967,9 @@ export class Repository implements Disposable {
} }
}); });
const promises: Promise<void>[] = []; await this.repository.clean(toClean);
await this.repository.checkout('', toCheckout);
if (toClean.length > 0) { await this.repository.updateSubmodules(submodulesToUpdate);
promises.push(this.repository.clean(toClean));
}
if (toCheckout.length > 0) {
promises.push(this.repository.checkout('', toCheckout));
}
if (submodulesToUpdate.length > 0) {
promises.push(this.repository.updateSubmodules(submodulesToUpdate));
}
await Promise.all(promises);
}); });
} }
@@ -1146,11 +1145,22 @@ export class Repository implements Disposable {
const config = workspace.getConfiguration('git', Uri.file(this.root)); const config = workspace.getConfiguration('git', Uri.file(this.root));
const fetchOnPull = config.get<boolean>('fetchOnPull'); const fetchOnPull = config.get<boolean>('fetchOnPull');
const tags = config.get<boolean>('pullTags'); const tags = config.get<boolean>('pullTags');
const supportCancellation = config.get<boolean>('supportCancellation');
if (fetchOnPull) { const fn = fetchOnPull
await this.repository.pull(rebase, undefined, undefined, { tags }); ? async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, undefined, undefined, { tags, cancellationToken })
: async (cancellationToken?: CancellationToken) => await this.repository.pull(rebase, remoteName, pullBranch, { tags, cancellationToken });
if (supportCancellation) {
const opts: ProgressOptions = {
location: ProgressLocation.Notification,
title: localize('sync is unpredictable', "Syncing. Cancelling may cause serious damages to the repository"),
cancellable: true
};
await window.withProgress(opts, (_, token) => fn(token));
} else { } else {
await this.repository.pull(rebase, remoteName, pullBranch, { tags }); await fn();
} }
const remote = this.remotes.find(r => r.name === remoteName); const remote = this.remotes.find(r => r.name === remoteName);
@@ -1495,15 +1505,7 @@ export class Repository implements Disposable {
this.workingTreeGroup.resourceStates = workingTree; this.workingTreeGroup.resourceStates = workingTree;
// set count badge // set count badge
const countBadge = workspace.getConfiguration('git').get<string>('countBadge'); this.setCountBadge();
let count = merge.length + index.length + workingTree.length;
switch (countBadge) {
case 'off': count = 0; break;
case 'tracked': count = count - workingTree.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED).length; break;
}
this._sourceControl.count = count;
// Disable `Discard All Changes` for "fresh" repositories // Disable `Discard All Changes` for "fresh" repositories
// https://github.com/Microsoft/vscode/issues/43066 // https://github.com/Microsoft/vscode/issues/43066
@@ -1517,6 +1519,18 @@ export class Repository implements Disposable {
this._onDidChangeStatus.fire(); this._onDidChangeStatus.fire();
} }
private setCountBadge(): void {
const countBadge = workspace.getConfiguration('git').get<string>('countBadge');
let count = this.mergeGroup.resourceStates.length + this.indexGroup.resourceStates.length + this.workingTreeGroup.resourceStates.length;
switch (countBadge) {
case 'off': count = 0; break;
case 'tracked': count = count - this.workingTreeGroup.resourceStates.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED).length; break;
}
this._sourceControl.count = count;
}
private async getRebaseCommit(): Promise<Commit | undefined> { private async getRebaseCommit(): Promise<Commit | undefined> {
const rebaseHeadPath = path.join(this.repository.root, '.git', 'REBASE_HEAD'); const rebaseHeadPath = path.join(this.repository.root, '.git', 'REBASE_HEAD');
const rebaseApplyPath = path.join(this.repository.root, '.git', 'rebase-apply'); const rebaseApplyPath = path.join(this.repository.root, '.git', 'rebase-apply');
@@ -1638,6 +1652,21 @@ export class Repository implements Disposable {
return `${this.HEAD.behind}${this.HEAD.ahead}`; return `${this.HEAD.behind}${this.HEAD.ahead}`;
} }
private updateInputBoxPlaceholder(): void {
const HEAD = this.HEAD;
if (HEAD) {
const tag = this.refs.filter(iref => iref.type === RefType.Tag && iref.commit === HEAD.commit)[0];
const tagName = tag && tag.name;
const head = HEAD.name || tagName || (HEAD.commit || '').substr(0, 8);
// '{0}' will be replaced by the corresponding key-command later in the process, which is why it needs to stay.
this._sourceControl.inputBox.placeholder = localize('commitMessageWithHeadLabel', "Message ({0} to commit on '{1}')", "{0}", head);
} else {
this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message ({0} to commit)");
}
}
dispose(): void { dispose(): void {
this.disposables = dispose(this.disposables); this.disposables = dispose(this.disposables);
} }

View File

@@ -5,7 +5,7 @@
import { Disposable, Command, EventEmitter, Event, workspace, Uri } from 'vscode'; import { Disposable, Command, EventEmitter, Event, workspace, Uri } from 'vscode';
import { Repository, Operation } from './repository'; import { Repository, Operation } from './repository';
import { anyEvent, dispose } from './util'; import { anyEvent, dispose, filterEvent } from './util';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { Branch } from './api/git'; import { Branch } from './api/git';
@@ -27,7 +27,7 @@ class CheckoutStatusBar {
return { return {
command: 'git.checkout', command: 'git.checkout',
tooltip: localize('checkout', 'Checkout...'), tooltip: `${this.repository.headLabel}`,
title, title,
arguments: [this.repository.sourceControl] arguments: [this.repository.sourceControl]
}; };
@@ -39,6 +39,7 @@ class CheckoutStatusBar {
} }
interface SyncStatusBarState { interface SyncStatusBarState {
enabled: boolean;
isSyncRunning: boolean; isSyncRunning: boolean;
hasRemotes: boolean; hasRemotes: boolean;
HEAD: Branch | undefined; HEAD: Branch | undefined;
@@ -47,6 +48,7 @@ interface SyncStatusBarState {
class SyncStatusBar { class SyncStatusBar {
private static StartState: SyncStatusBarState = { private static StartState: SyncStatusBarState = {
enabled: true,
isSyncRunning: false, isSyncRunning: false,
hasRemotes: false, hasRemotes: false,
HEAD: undefined HEAD: undefined
@@ -66,9 +68,20 @@ class SyncStatusBar {
constructor(private repository: Repository) { constructor(private repository: Repository) {
repository.onDidRunGitStatus(this.onModelChange, this, this.disposables); repository.onDidRunGitStatus(this.onModelChange, this, this.disposables);
repository.onDidChangeOperations(this.onOperationsChange, this, this.disposables); repository.onDidChangeOperations(this.onOperationsChange, this, this.disposables);
const onEnablementChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.enableStatusBarSync'));
onEnablementChange(this.updateEnablement, this, this.disposables);
this._onDidChange.fire(); this._onDidChange.fire();
} }
private updateEnablement(): void {
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
const enabled = config.get<boolean>('enableStatusBarSync', true);
this.state = { ... this.state, enabled };
}
private onOperationsChange(): void { private onOperationsChange(): void {
const isSyncRunning = this.repository.operations.isRunning(Operation.Sync) || const isSyncRunning = this.repository.operations.isRunning(Operation.Sync) ||
this.repository.operations.isRunning(Operation.Push) || this.repository.operations.isRunning(Operation.Push) ||
@@ -86,7 +99,7 @@ class SyncStatusBar {
} }
get command(): Command | undefined { get command(): Command | undefined {
if (!this.state.hasRemotes) { if (!this.state.enabled || !this.state.hasRemotes) {
return undefined; return undefined;
} }

View File

@@ -6,6 +6,7 @@
import 'mocha'; import 'mocha';
import { GitStatusParser, parseGitCommit, parseGitmodules, parseLsTree, parseLsFiles } from '../git'; import { GitStatusParser, parseGitCommit, parseGitmodules, parseLsTree, parseLsFiles } from '../git';
import * as assert from 'assert'; import * as assert from 'assert';
import { splitInChunks } from '../util';
suite('git', () => { suite('git', () => {
suite('GitStatusParser', () => { suite('GitStatusParser', () => {
@@ -292,4 +293,78 @@ This is a commit message.`;
]); ]);
}); });
}); });
});
suite('splitInChunks', () => {
test('unit tests', function () {
assert.deepEqual(
[...splitInChunks(['hello', 'there', 'cool', 'stuff'], 6)],
[['hello'], ['there'], ['cool'], ['stuff']]
);
assert.deepEqual(
[...splitInChunks(['hello', 'there', 'cool', 'stuff'], 10)],
[['hello', 'there'], ['cool', 'stuff']]
);
assert.deepEqual(
[...splitInChunks(['hello', 'there', 'cool', 'stuff'], 12)],
[['hello', 'there'], ['cool', 'stuff']]
);
assert.deepEqual(
[...splitInChunks(['hello', 'there', 'cool', 'stuff'], 14)],
[['hello', 'there', 'cool'], ['stuff']]
);
assert.deepEqual(
[...splitInChunks(['hello', 'there', 'cool', 'stuff'], 2000)],
[['hello', 'there', 'cool', 'stuff']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 1)],
[['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 2)],
[['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 3)],
[['0', '01'], ['012'], ['0', '01'], ['012'], ['0', '01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 4)],
[['0', '01'], ['012', '0'], ['01'], ['012', '0'], ['01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 5)],
[['0', '01'], ['012', '0'], ['01', '012'], ['0', '01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 6)],
[['0', '01', '012'], ['0', '01', '012'], ['0', '01', '012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 7)],
[['0', '01', '012', '0'], ['01', '012', '0'], ['01', '012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 8)],
[['0', '01', '012', '0'], ['01', '012', '0', '01'], ['012']]
);
assert.deepEqual(
[...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 9)],
[['0', '01', '012', '0', '01'], ['012', '0', '01', '012']]
);
});
});
});

View File

@@ -3,8 +3,8 @@
* 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 { Event, EventEmitter, Uri } from 'vscode'; import { Event } from 'vscode';
import { dirname, sep, join } from 'path'; import { dirname, sep } from 'path';
import { Readable } from 'stream'; import { Readable } from 'stream';
import * as fs from 'fs'; import * as fs from 'fs';
import * as byline from 'byline'; import * as byline from 'byline';
@@ -345,18 +345,69 @@ export function pathEquals(a: string, b: string): boolean {
return a === b; return a === b;
} }
export interface IFileWatcher extends IDisposable { export function* splitInChunks(array: string[], maxChunkLength: number): IterableIterator<string[]> {
readonly event: Event<Uri>; let current: string[] = [];
let length = 0;
for (const value of array) {
let newLength = length + value.length;
if (newLength > maxChunkLength && current.length > 0) {
yield current;
current = [];
newLength = value.length;
}
current.push(value);
length = newLength;
}
if (current.length > 0) {
yield current;
}
} }
export function watch(location: string): IFileWatcher { interface ILimitedTaskFactory<T> {
const dotGitWatcher = fs.watch(location); factory: () => Promise<T>;
const onDotGitFileChangeEmitter = new EventEmitter<Uri>(); c: (value?: T | Promise<T>) => void;
dotGitWatcher.on('change', (_, e) => onDotGitFileChangeEmitter.fire(Uri.file(join(location, e as string)))); e: (error?: any) => void;
dotGitWatcher.on('error', err => console.error(err)); }
return new class implements IFileWatcher { export class Limiter<T> {
event = onDotGitFileChangeEmitter.event;
dispose() { dotGitWatcher.close(); } private runningPromises: number;
}; private maxDegreeOfParalellism: number;
private outstandingPromises: ILimitedTaskFactory<T>[];
constructor(maxDegreeOfParalellism: number) {
this.maxDegreeOfParalellism = maxDegreeOfParalellism;
this.outstandingPromises = [];
this.runningPromises = 0;
}
queue(factory: () => Promise<T>): Promise<T> {
return new Promise<T>((c, e) => {
this.outstandingPromises.push({ factory, c, e });
this.consume();
});
}
private consume(): void {
while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) {
const iLimitedTask = this.outstandingPromises.shift()!;
this.runningPromises++;
const promise = iLimitedTask.factory();
promise.then(iLimitedTask.c, iLimitedTask.e);
promise.then(() => this.consumed(), () => this.consumed());
}
}
private consumed(): void {
this.runningPromises--;
if (this.outstandingPromises.length > 0) {
this.consume();
}
}
} }

View File

@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, EventEmitter, Uri } from 'vscode';
import { join } from 'path';
import * as fs from 'fs';
import { IDisposable } from './util';
export interface IFileWatcher extends IDisposable {
readonly event: Event<Uri>;
}
export function watch(location: string): IFileWatcher {
const dotGitWatcher = fs.watch(location);
const onDotGitFileChangeEmitter = new EventEmitter<Uri>();
dotGitWatcher.on('change', (_, e) => onDotGitFileChangeEmitter.fire(Uri.file(join(location, e as string))));
dotGitWatcher.on('error', err => console.error(err));
return new class implements IFileWatcher {
event = onDotGitFileChangeEmitter.event;
dispose() { dotGitWatcher.close(); }
};
}

View File

@@ -223,7 +223,7 @@ export function activate(context: ExtensionContext) {
let languageConfiguration: LanguageConfiguration = { let languageConfiguration: LanguageConfiguration = {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/, wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: { indentationRules: {
increaseIndentPattern: /^.*(\{[^}]*|\[[^\]]*)$/, increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
decreaseIndentPattern: /^\s*[}\]],?\s*$/ decreaseIndentPattern: /^\s*[}\]],?\s*$/
} }
}; };

View File

@@ -50,7 +50,8 @@
".babelrc", ".babelrc",
".jsonc", ".jsonc",
".eslintrc", ".eslintrc",
".eslintrc.json" ".eslintrc.json",
"tslint.json"
], ],
"configuration": "./language-configuration.json" "configuration": "./language-configuration.json"
} }
@@ -74,4 +75,4 @@
} }
] ]
} }
} }

View File

@@ -2566,4 +2566,4 @@
"name": "markup.inline.raw.string.markdown" "name": "markup.inline.raw.string.markdown"
} }
} }
} }

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.5.2" "typescript": "3.6.0-dev.20190810"
}, },
"scripts": { "scripts": {
"postinstall": "node ./postinstall" "postinstall": "node ./postinstall"

View File

@@ -5,13 +5,13 @@
"type": "git", "type": "git",
"git": { "git": {
"name": "PowerShell/EditorSyntax", "name": "PowerShell/EditorSyntax",
"repositoryUrl": "https://github.com/powershell/editorsyntax", "repositoryUrl": "https://github.com/PowerShell/EditorSyntax",
"commitHash": "12b7d7257eb493e45a9af0af9094ec0c2a996712" "commitHash": "d10ae29c0d3ceb248172c383a159ae43b9ccfb4d"
} }
}, },
"license": "MIT", "license": "MIT",
"version": "0.0.0" "version": "1.0.0"
} }
], ],
"version": 1 "version": 1
} }

View File

@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.", "If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request." "Once accepted there, we are happy to receive an update request."
], ],
"version": "https://github.com/PowerShell/EditorSyntax/commit/44eac8702f3cbe55a4ec70c1fdb163d42b4162fc", "version": "https://github.com/PowerShell/EditorSyntax/commit/d10ae29c0d3ceb248172c383a159ae43b9ccfb4d",
"name": "PowerShell", "name": "PowerShell",
"scopeName": "source.powershell", "scopeName": "source.powershell",
"patterns": [ "patterns": [
@@ -670,7 +670,7 @@
} }
}, },
"comment": "Style preference variables as language variables so that they stand out.", "comment": "Style preference variables as language variables so that they stand out.",
"match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?\\b" "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|VerbosePreference|WarningPreference|WhatIfPreference))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?\\b"
}, },
{ {
"captures": { "captures": {
@@ -848,7 +848,7 @@
} }
}, },
"comment": "Style preference variables as language variables so that they stand out.", "comment": "Style preference variables as language variables so that they stand out.",
"match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))\\b" "match": "(\\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|VerbosePreference|WarningPreference|WhatIfPreference))\\b"
}, },
{ {
"captures": { "captures": {

View File

@@ -465,11 +465,11 @@
"c": ".IsInRole", "c": ".IsInRole",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell variable.other.member.powershell", "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell variable.other.member.powershell",
"r": { "r": {
"dark_plus": "variable: #9CDCFE", "dark_plus": "source.powershell variable.other.member: #DCDCAA",
"light_plus": "variable: #001080", "light_plus": "source.powershell variable.other.member: #795E26",
"dark_vs": "default: #D4D4D4", "dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000", "light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE" "hc_black": "source.powershell variable.other.member: #DCDCAA"
} }
}, },
{ {

View File

@@ -8,7 +8,8 @@
"scope": [ "scope": [
"entity.name.function", "entity.name.function",
"support.function", "support.function",
"support.constant.handlebars" "support.constant.handlebars",
"source.powershell variable.other.member"
], ],
"settings": { "settings": {
"foreground": "#DCDCAA" "foreground": "#DCDCAA"
@@ -171,4 +172,4 @@
} }
} }
] ]
} }

View File

@@ -13,7 +13,8 @@
"scope": [ "scope": [
"entity.name.function", "entity.name.function",
"support.function", "support.function",
"support.constant.handlebars" "support.constant.handlebars",
"source.powershell variable.other.member"
], ],
"settings": { "settings": {
"foreground": "#DCDCAA" "foreground": "#DCDCAA"
@@ -115,4 +116,4 @@
} }
} }
] ]
} }

View File

@@ -8,7 +8,8 @@
"scope": [ "scope": [
"entity.name.function", "entity.name.function",
"support.function", "support.function",
"support.constant.handlebars" "support.constant.handlebars",
"source.powershell variable.other.member"
], ],
"settings": { "settings": {
"foreground": "#795E26" "foreground": "#795E26"
@@ -172,4 +173,4 @@
} }
] ]
} }

View File

@@ -2,7 +2,7 @@
# yarn lockfile v1 # yarn lockfile v1
typescript@3.5.2: typescript@3.6.0-dev.20190810:
version "3.5.2" version "3.6.0-dev.20190810"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.0-dev.20190810.tgz#dda80279480131eec9b05e3b78182a1ba1efe105"
integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== integrity sha512-gubcQ8Sn2G5AO1KhjvLpoFrutV7o/ZJ7wCDBC1IKgNI8R2vadIxTystJxAFqkb9boQ7tyRrZ6FwM5EL5ZYfJrg==

View File

@@ -40,6 +40,7 @@
"@angular/platform-browser-dynamic": "~4.1.3", "@angular/platform-browser-dynamic": "~4.1.3",
"@angular/router": "~4.1.3", "@angular/router": "~4.1.3",
"@angular/upgrade": "~4.1.3", "@angular/upgrade": "~4.1.3",
"@microsoft/applicationinsights-web": "^2.1.1",
"angular2-grid": "2.0.6", "angular2-grid": "2.0.6",
"angular2-slickgrid": "github:Microsoft/angular2-slickgrid#1.4.6", "angular2-slickgrid": "github:Microsoft/angular2-slickgrid#1.4.6",
"ansi_up": "^3.0.0", "ansi_up": "^3.0.0",
@@ -53,8 +54,7 @@
"jquery": "3.4.0", "jquery": "3.4.0",
"jschardet": "1.6.0", "jschardet": "1.6.0",
"keytar": "^4.11.0", "keytar": "^4.11.0",
"minimist": "1.2.0", "native-is-elevated": "0.3.0",
"native-is-elevated": "^0.2.1",
"native-keymap": "2.0.0", "native-keymap": "2.0.0",
"native-watchdog": "1.0.0", "native-watchdog": "1.0.0",
"ng2-charts": "^1.6.0", "ng2-charts": "^1.6.0",
@@ -72,11 +72,12 @@
"underscore": "^1.8.2", "underscore": "^1.8.2",
"v8-inspect-profiler": "^0.0.20", "v8-inspect-profiler": "^0.0.20",
"vscode-chokidar": "2.1.7", "vscode-chokidar": "2.1.7",
"vscode-minimist": "^1.2.1",
"vscode-proxy-agent": "0.4.0", "vscode-proxy-agent": "0.4.0",
"vscode-ripgrep": "^1.5.5", "vscode-ripgrep": "^1.5.6",
"vscode-sqlite3": "4.0.8", "vscode-sqlite3": "4.0.8",
"vscode-textmate": "^4.2.2", "vscode-textmate": "^4.2.2",
"xterm": "3.15.0-beta90", "xterm": "3.15.0-beta98",
"xterm-addon-search": "0.2.0-beta3", "xterm-addon-search": "0.2.0-beta3",
"xterm-addon-web-links": "0.1.0-beta10", "xterm-addon-web-links": "0.1.0-beta10",
"yauzl": "^2.9.2", "yauzl": "^2.9.2",
@@ -88,7 +89,6 @@
"@types/chart.js": "^2.7.31", "@types/chart.js": "^2.7.31",
"@types/htmlparser2": "^3.7.31", "@types/htmlparser2": "^3.7.31",
"@types/keytar": "^4.4.0", "@types/keytar": "^4.4.0",
"@types/minimist": "^1.2.0",
"@types/mocha": "2.2.39", "@types/mocha": "2.2.39",
"@types/node": "^10.12.12", "@types/node": "^10.12.12",
"@types/sanitize-html": "^1.18.2", "@types/sanitize-html": "^1.18.2",
@@ -187,7 +187,7 @@
}, },
"optionalDependencies": { "optionalDependencies": {
"vscode-windows-ca-certs": "0.1.0", "vscode-windows-ca-certs": "0.1.0",
"vscode-windows-registry": "1.0.1", "vscode-windows-registry": "1.0.2",
"windows-foreground-love": "0.2.0", "windows-foreground-love": "0.2.0",
"windows-mutex": "0.3.0", "windows-mutex": "0.3.0",
"windows-process-tree": "0.2.4" "windows-process-tree": "0.2.4"

View File

@@ -2,6 +2,7 @@
"name": "vscode-reh", "name": "vscode-reh",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@microsoft/applicationinsights-web": "^2.1.1",
"applicationinsights": "1.0.8", "applicationinsights": "1.0.8",
"getmac": "1.4.1", "getmac": "1.4.1",
"graceful-fs": "4.1.11", "graceful-fs": "4.1.11",
@@ -9,7 +10,6 @@
"https-proxy-agent": "^2.2.1", "https-proxy-agent": "^2.2.1",
"iconv-lite": "0.5.0", "iconv-lite": "0.5.0",
"jschardet": "1.6.0", "jschardet": "1.6.0",
"minimist": "1.2.0",
"native-watchdog": "1.0.0", "native-watchdog": "1.0.0",
"node-pty": "0.9.0-beta19", "node-pty": "0.9.0-beta19",
"nsfw": "1.2.5", "nsfw": "1.2.5",
@@ -17,10 +17,11 @@
"semver-umd": "^5.5.3", "semver-umd": "^5.5.3",
"spdlog": "^0.9.0", "spdlog": "^0.9.0",
"vscode-chokidar": "2.1.7", "vscode-chokidar": "2.1.7",
"vscode-minimist": "^1.2.1",
"vscode-proxy-agent": "0.4.0", "vscode-proxy-agent": "0.4.0",
"vscode-ripgrep": "^1.5.5", "vscode-ripgrep": "^1.5.6",
"vscode-textmate": "^4.2.2", "vscode-textmate": "^4.2.2",
"xterm": "3.15.0-beta90", "xterm": "3.15.0-beta98",
"xterm-addon-search": "0.2.0-beta3", "xterm-addon-search": "0.2.0-beta3",
"xterm-addon-web-links": "0.1.0-beta10", "xterm-addon-web-links": "0.1.0-beta10",
"yauzl": "^2.9.2", "yauzl": "^2.9.2",

View File

@@ -2,6 +2,7 @@
"name": "vscode-web", "name": "vscode-web",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@microsoft/applicationinsights-web": "^2.1.1",
"onigasm-umd": "^2.2.2", "onigasm-umd": "^2.2.2",
"vscode-textmate": "^4.1.1", "vscode-textmate": "^4.1.1",
"xterm": "3.15.0-beta67", "xterm": "3.15.0-beta67",

View File

@@ -2,6 +2,69 @@
# yarn lockfile v1 # yarn lockfile v1
"@microsoft/applicationinsights-analytics-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.1.1.tgz#6d09c1915f808026e2d45165d04802f09affed59"
integrity sha512-VKIutoFKY99CyKwxLUuj6Vnq14/QwXo9/QSQDpYnHEjo+uKn7QmLsHqWw0K9uYNfNAXt4BZimX/zDg6jZtzeXg==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-channel-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.1.1.tgz#e205eddd93e49d17d9e0711a612b4bfc9810888f"
integrity sha512-fYr9IAqtaEr9AmaPaL3SLQVT3t3GQzl+n74gpNKyAVakDIm0nYQ/bimjdcAhJMDf1VGNSPg/xICneyuZg7Wxlg==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-common@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.1.1.tgz#27e6074584a7a3a8ca3f11f7ff2b7ff0f395bf2d"
integrity sha512-2hkS1Ia1FmAjCuYZ5JlG20/WgObqdsKtmK5YALAFGHIB4KSQ/Za1qazS+7GsG+E0F9UJivNWL1geUIcNqg5Qjg==
dependencies:
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-core-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.1.1.tgz#30fb6a519cc1c6119c419c4811ce72c260217d9e"
integrity sha512-4t4wf6SKqIcWEQDPg/uOhm+BxtHhu/AFreyEoYZmMfcxzAu33h1FtTQRtxBNbYH1+thiNZCh80yUpnT7d9Hrlw==
dependencies:
tslib "^1.9.3"
"@microsoft/applicationinsights-dependencies-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.1.1.tgz#8154c3efcb24617d015d0bce7c2cc47797a8d3c4"
integrity sha512-yhb4EToBp+aI+qLo0h5NDNtoo3sDFV60uyIOK843YjzXqVotcXX/lRShlghTkJtYH09QhrdzDjViUHnD4sMFSQ==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-properties-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.1.1.tgz#ca34232766eb16167b5d87693e2ae5d94f2a1559"
integrity sha512-8l+/ppw6xKTam2RL4EHZ52Lcf217olw81j6kyBNKtIcGwSnLNHrFwEeF3vBWIteG2JKzlg1GhGjrkB3oxXsV2g==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-web@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web/-/applicationinsights-web-2.1.1.tgz#1a44eddda7c244b88d9eb052dab6c855682e4f05"
integrity sha512-crvhCkNsNxkFuPWmttyWNSAA96D5FxBtKS6UA9MV9f9XHevTfchf/E3AuU9JZcsXufWMQLwLrUQ9ZiA1QJ0EWA==
dependencies:
"@microsoft/applicationinsights-analytics-js" "2.1.1"
"@microsoft/applicationinsights-channel-js" "2.1.1"
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
"@microsoft/applicationinsights-dependencies-js" "2.1.1"
"@microsoft/applicationinsights-properties-js" "2.1.1"
nan@^2.14.0: nan@^2.14.0:
version "2.14.0" version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
@@ -24,6 +87,11 @@ semver-umd@^5.5.3:
resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e" resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e"
integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw== integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw==
tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
vscode-textmate@^4.1.1: vscode-textmate@^4.1.1:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c" resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.2.2.tgz#0b4dabc69a6fba79a065cb6b615f66eac07c8f4c"

View File

@@ -2,6 +2,69 @@
# yarn lockfile v1 # yarn lockfile v1
"@microsoft/applicationinsights-analytics-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.1.1.tgz#6d09c1915f808026e2d45165d04802f09affed59"
integrity sha512-VKIutoFKY99CyKwxLUuj6Vnq14/QwXo9/QSQDpYnHEjo+uKn7QmLsHqWw0K9uYNfNAXt4BZimX/zDg6jZtzeXg==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-channel-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.1.1.tgz#e205eddd93e49d17d9e0711a612b4bfc9810888f"
integrity sha512-fYr9IAqtaEr9AmaPaL3SLQVT3t3GQzl+n74gpNKyAVakDIm0nYQ/bimjdcAhJMDf1VGNSPg/xICneyuZg7Wxlg==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-common@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.1.1.tgz#27e6074584a7a3a8ca3f11f7ff2b7ff0f395bf2d"
integrity sha512-2hkS1Ia1FmAjCuYZ5JlG20/WgObqdsKtmK5YALAFGHIB4KSQ/Za1qazS+7GsG+E0F9UJivNWL1geUIcNqg5Qjg==
dependencies:
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-core-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.1.1.tgz#30fb6a519cc1c6119c419c4811ce72c260217d9e"
integrity sha512-4t4wf6SKqIcWEQDPg/uOhm+BxtHhu/AFreyEoYZmMfcxzAu33h1FtTQRtxBNbYH1+thiNZCh80yUpnT7d9Hrlw==
dependencies:
tslib "^1.9.3"
"@microsoft/applicationinsights-dependencies-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.1.1.tgz#8154c3efcb24617d015d0bce7c2cc47797a8d3c4"
integrity sha512-yhb4EToBp+aI+qLo0h5NDNtoo3sDFV60uyIOK843YjzXqVotcXX/lRShlghTkJtYH09QhrdzDjViUHnD4sMFSQ==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-properties-js@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.1.1.tgz#ca34232766eb16167b5d87693e2ae5d94f2a1559"
integrity sha512-8l+/ppw6xKTam2RL4EHZ52Lcf217olw81j6kyBNKtIcGwSnLNHrFwEeF3vBWIteG2JKzlg1GhGjrkB3oxXsV2g==
dependencies:
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
tslib "^1.9.3"
"@microsoft/applicationinsights-web@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web/-/applicationinsights-web-2.1.1.tgz#1a44eddda7c244b88d9eb052dab6c855682e4f05"
integrity sha512-crvhCkNsNxkFuPWmttyWNSAA96D5FxBtKS6UA9MV9f9XHevTfchf/E3AuU9JZcsXufWMQLwLrUQ9ZiA1QJ0EWA==
dependencies:
"@microsoft/applicationinsights-analytics-js" "2.1.1"
"@microsoft/applicationinsights-channel-js" "2.1.1"
"@microsoft/applicationinsights-common" "2.1.1"
"@microsoft/applicationinsights-core-js" "2.1.1"
"@microsoft/applicationinsights-dependencies-js" "2.1.1"
"@microsoft/applicationinsights-properties-js" "2.1.1"
agent-base@4, agent-base@^4.1.0: agent-base@4, agent-base@^4.1.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
@@ -660,11 +723,6 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
mixin-deep@^1.2.0: mixin-deep@^1.2.0:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -1029,6 +1087,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2" regex-not "^1.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
typechecker@^4.3.0: typechecker@^4.3.0:
version "4.7.0" version "4.7.0"
resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9"
@@ -1113,6 +1176,11 @@ vscode-fsevents@1.2.12:
dependencies: dependencies:
nan "^2.14.0" nan "^2.14.0"
vscode-minimist@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/vscode-minimist/-/vscode-minimist-1.2.1.tgz#e63d3f4a9bf3680dcb8f9304eed612323fd6926a"
integrity sha512-cmB72+qDoiCFJ1UKnGUBdGYfXzdpJ3bQM/D/+XhkVk5v7uZgLbYiCz5JcwVyk7NC7hSi5VGtQ4wihzmi12NeXw==
vscode-proxy-agent@0.4.0: vscode-proxy-agent@0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.4.0.tgz#574833e65405c6333f350f1b9fef9909deccb6b5" resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.4.0.tgz#574833e65405c6333f350f1b9fef9909deccb6b5"
@@ -1123,10 +1191,10 @@ vscode-proxy-agent@0.4.0:
https-proxy-agent "2.2.1" https-proxy-agent "2.2.1"
socks-proxy-agent "4.0.1" socks-proxy-agent "4.0.1"
vscode-ripgrep@^1.5.5: vscode-ripgrep@^1.5.6:
version "1.5.5" version "1.5.6"
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.5.tgz#24c0e9cb356cf889c98e15ecb58f9cf654a1d961" resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.6.tgz#93bf5c99ca5f8248950a305e224f6ca153c30af4"
integrity sha512-OrPrAmcun4+uZAuNcQvE6CCPskh+5AsjANod/Q3zRcJcGNxgoOSGlQN9RPtatkUNmkN8Nn8mZBnS1jMylu/dKg== integrity sha512-WRIM9XpUj6dsfdAmuI3ANbmT1ysPUVsYy/2uCLDHJa9kbiB4T7uGvFnnc0Rgx2qQnyRAwL7PeWaFgUljPPxf2g==
vscode-textmate@^4.2.2: vscode-textmate@^4.2.2:
version "4.2.2" version "4.2.2"
@@ -1159,10 +1227,10 @@ xterm-addon-web-links@0.1.0-beta10:
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23"
integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg== integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg==
xterm@3.15.0-beta90: xterm@3.15.0-beta98:
version "3.15.0-beta90" version "3.15.0-beta98"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta90.tgz#e1732c2914584c86cffa797ba762c482f21ce182" resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta98.tgz#37f37c35577422880e7ef673cc37f9d2a45dd40c"
integrity sha512-eixIA5brfoez+Y8bJPCcIw8Q7LgOvxRX3cPBaGmo7ozUASx9IEGOmvIRQX1ozTUmxEiXPnAxOfl/isQ+yNlaww== integrity sha512-vZbg2LcRvoiJOgr1MyeLFM9mF4uib3BWUWDHyFc+vZ58CTuK0iczOvFXgk/ySo23ZLqwmHQSigLgmWvZ8J5G0Q==
yauzl@^2.9.2: yauzl@^2.9.2:
version "2.10.0" version "2.10.0"

View File

@@ -1,4 +1,4 @@
_code() _@@APPNAME@@()
{ {
local cur prev words cword split local cur prev words cword split
_init_completion -s || return _init_completion -s || return
@@ -58,4 +58,4 @@ _code()
_filedir _filedir
} && } &&
complete -F _code code complete -F _@@APPNAME@@ @@APPNAME@@

View File

@@ -1,4 +1,4 @@
#compdef code #compdef @@APPNAME@@
local arguments local arguments
@@ -14,7 +14,7 @@ arguments=(
'--user-data-dir[specify the directory that user data is kept in]:directory:_directories' '--user-data-dir[specify the directory that user data is kept in]:directory:_directories'
'(- *)'{-v,--version}'[print version]' '(- *)'{-v,--version}'[print version]'
'(- *)'{-h,--help}'[print usage]' '(- *)'{-h,--help}'[print usage]'
'(- *)'{--telemetry}'[Shows all telemetry events which VS code collects.]' '--telemetry[show all telemetry events which VS code collects]'
'--extensions-dir[set the root path for extensions]:root path:_directories' '--extensions-dir[set the root path for extensions]:root path:_directories'
'--list-extensions[list the installed extensions]' '--list-extensions[list the installed extensions]'
'--category[filters instaled extension list by category, when using --list-extension]' '--category[filters instaled extension list by category, when using --list-extension]'

View File

@@ -18,14 +18,14 @@ Visual Studio Code is a new choice of tool that combines the simplicity of a cod
mkdir -p %{buildroot}/usr/share/@@NAME@@ mkdir -p %{buildroot}/usr/share/@@NAME@@
mkdir -p %{buildroot}/usr/share/applications mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/pixmaps mkdir -p %{buildroot}/usr/share/pixmaps
#mkdir -p %{buildroot}/usr/share/bash-completion/completions mkdir -p %{buildroot}/usr/share/bash-completion/completions
#mkdir -p %{buildroot}/usr/share/zsh/site-functions mkdir -p %{buildroot}/usr/share/zsh/site-functions
cp -r usr/share/@@NAME@@/* %{buildroot}/usr/share/@@NAME@@ cp -r usr/share/@@NAME@@/* %{buildroot}/usr/share/@@NAME@@
cp -r usr/share/applications/@@NAME@@.desktop %{buildroot}/usr/share/applications cp -r usr/share/applications/@@NAME@@.desktop %{buildroot}/usr/share/applications
cp -r usr/share/applications/@@NAME@@-url-handler.desktop %{buildroot}/usr/share/applications cp -r usr/share/applications/@@NAME@@-url-handler.desktop %{buildroot}/usr/share/applications
cp -r usr/share/pixmaps/@@ICON@@.png %{buildroot}/usr/share/pixmaps cp -r usr/share/pixmaps/@@ICON@@.png %{buildroot}/usr/share/pixmaps
#cp usr/share/bash-completion/completions/code %{buildroot}/usr/share/bash-completion/completions/code cp usr/share/bash-completion/completions/@@NAME@@ %{buildroot}/usr/share/bash-completion/completions/@@NAME@@
#cp usr/share/zsh/site-functions/_code %{buildroot}/usr/share/zsh/site-functions/_code cp usr/share/zsh/site-functions/_@@NAME@@ %{buildroot}/usr/share/zsh/site-functions/_@@NAME@@
%post %post
# Remove the legacy bin command if this is the stable build # Remove the legacy bin command if this is the stable build
@@ -58,5 +58,5 @@ fi
/usr/share/applications/@@NAME@@.desktop /usr/share/applications/@@NAME@@.desktop
/usr/share/applications/@@NAME@@-url-handler.desktop /usr/share/applications/@@NAME@@-url-handler.desktop
/usr/share/pixmaps/@@ICON@@.png /usr/share/pixmaps/@@ICON@@.png
#/usr/share/bash-completion/completions/code /usr/share/bash-completion/completions/@@NAME@@
#/usr/share/zsh/site-functions/_code /usr/share/zsh/site-functions/_@@NAME@@

View File

@@ -3,6 +3,10 @@
* 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.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
function entrypoint (name) {
return [{ name: name, include: [], exclude: ['vs/css', 'vs/nls'] }];
}
exports.base = [{ exports.base = [{
name: 'vs/base/common/worker/simpleWorker', name: 'vs/base/common/worker/simpleWorker',
include: ['vs/editor/common/services/editorSimpleWorker'], include: ['vs/editor/common/services/editorSimpleWorker'],
@@ -19,11 +23,15 @@ exports.serviceWorker = [{
dest: 'vs/workbench/contrib/resources/browser/resourceServiceWorkerMain.js' dest: 'vs/workbench/contrib/resources/browser/resourceServiceWorkerMain.js'
}]; }];
exports.workbench = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.main']); exports.workbench = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.desktop.main']);
exports.workbenchWeb = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.web.api']); exports.workbenchWeb = entrypoint('vs/workbench/workbench.web.api');
exports.keyboardMaps = [
entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.linux'),
entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.darwin'),
entrypoint('vs/workbench/services/keybinding/browser/keyboardLayouts/layout.contribution.win')
];
exports.code = require('./vs/code/buildfile').collectModules(); exports.code = require('./vs/code/buildfile').collectModules();
exports.entrypoint = function (name) { exports.entrypoint = entrypoint;
return [{ name: name, include: [], exclude: ['vs/css', 'vs/nls'] }];
};

View File

@@ -133,7 +133,7 @@ function onReady() {
} }
/** /**
* @typedef {import('minimist').ParsedArgs} ParsedArgs * @typedef {{ [arg: string]: any; '--'?: string[]; _: string[]; }} ParsedArgs
* *
* @param {ParsedArgs} cliArgs * @param {ParsedArgs} cliArgs
*/ */
@@ -186,7 +186,7 @@ function getUserDataPath(cliArgs) {
* @returns {ParsedArgs} * @returns {ParsedArgs}
*/ */
function parseCLIArgs() { function parseCLIArgs() {
const minimist = require('minimist'); const minimist = require('vscode-minimist');
return minimist(process.argv, { return minimist(process.argv, {
string: [ string: [

View File

@@ -3,9 +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 extHostApi from 'vs/workbench/api/node/extHost.api.impl'; import * as extHostApi from 'vs/workbench/api/common/extHost.api.impl';
import { IInitData, IMainContext } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
@@ -35,13 +33,15 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/c
import { ExtHostExtensionManagement } from 'sql/workbench/api/common/extHostExtensionManagement'; import { ExtHostExtensionManagement } from 'sql/workbench/api/common/extHostExtensionManagement';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { TernarySearchTree } from 'vs/base/common/map'; import { TernarySearchTree } from 'vs/base/common/map';
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
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 { IURITransformer } from 'vs/base/common/uriIpc';
import { mssqlProviderName } from 'sql/platform/connection/common/constants'; import { mssqlProviderName } from 'sql/platform/connection/common/constants';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ILogService } from 'vs/platform/log/common/log';
export interface ISqlExtensionApiFactory { export interface ISqlExtensionApiFactory {
vsCodeFactory(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; vsCodeFactory(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -52,17 +52,12 @@ export interface ISqlExtensionApiFactory {
/** /**
* This method instantiates and returns the extension API surface * This method instantiates and returns the extension API surface
*/ */
export function createApiFactory( export function createApiFactory(accessor: ServicesAccessor): ISqlExtensionApiFactory {
initData: IInitData, const instaServer = accessor.get(IInstantiationService);
rpcProtocol: IMainContext, const uriTransformer = accessor.get(IURITransformerService);
extHostWorkspace: ExtHostWorkspace, const rpcProtocol = accessor.get(IExtHostRpcService);
extHostConfiguration: ExtHostConfiguration, const extHostLogService = <ExtHostLogService>accessor.get(ILogService);
extensionService: ExtHostExtensionService, let vsCodeFactory = instaServer.invokeFunction(extHostApi.createApiFactoryAndRegisterActors);
logService: ExtHostLogService,
extHostStorage: ExtHostStorage,
uriTransformer: IURITransformer | null
): ISqlExtensionApiFactory {
let vsCodeFactory = extHostApi.createApiFactory(initData, rpcProtocol, extHostWorkspace, extHostConfiguration, extensionService, logService, extHostStorage, uriTransformer);
// Addressable instances // Addressable instances
const extHostAccountManagement = rpcProtocol.set(SqlExtHostContext.ExtHostAccountManagement, new ExtHostAccountManagement(rpcProtocol)); const extHostAccountManagement = rpcProtocol.set(SqlExtHostContext.ExtHostAccountManagement, new ExtHostAccountManagement(rpcProtocol));
@@ -72,7 +67,7 @@ export function createApiFactory(
const extHostObjectExplorer = rpcProtocol.set(SqlExtHostContext.ExtHostObjectExplorer, new ExtHostObjectExplorer(rpcProtocol)); const extHostObjectExplorer = rpcProtocol.set(SqlExtHostContext.ExtHostObjectExplorer, new ExtHostObjectExplorer(rpcProtocol));
const extHostResourceProvider = rpcProtocol.set(SqlExtHostContext.ExtHostResourceProvider, new ExtHostResourceProvider(rpcProtocol)); const extHostResourceProvider = rpcProtocol.set(SqlExtHostContext.ExtHostResourceProvider, new ExtHostResourceProvider(rpcProtocol));
const extHostModalDialogs = rpcProtocol.set(SqlExtHostContext.ExtHostModalDialogs, new ExtHostModalDialogs(rpcProtocol)); const extHostModalDialogs = rpcProtocol.set(SqlExtHostContext.ExtHostModalDialogs, new ExtHostModalDialogs(rpcProtocol));
const extHostTasks = rpcProtocol.set(SqlExtHostContext.ExtHostTasks, new ExtHostTasks(rpcProtocol, logService)); const extHostTasks = rpcProtocol.set(SqlExtHostContext.ExtHostTasks, new ExtHostTasks(rpcProtocol, extHostLogService));
const extHostBackgroundTaskManagement = rpcProtocol.set(SqlExtHostContext.ExtHostBackgroundTaskManagement, new ExtHostBackgroundTaskManagement(rpcProtocol)); const extHostBackgroundTaskManagement = rpcProtocol.set(SqlExtHostContext.ExtHostBackgroundTaskManagement, new ExtHostBackgroundTaskManagement(rpcProtocol));
const extHostWebviewWidgets = rpcProtocol.set(SqlExtHostContext.ExtHostDashboardWebviews, new ExtHostDashboardWebviews(rpcProtocol)); const extHostWebviewWidgets = rpcProtocol.set(SqlExtHostContext.ExtHostDashboardWebviews, new ExtHostDashboardWebviews(rpcProtocol));
const extHostModelViewTree = rpcProtocol.set(SqlExtHostContext.ExtHostModelViewTreeViews, new ExtHostModelViewTreeViews(rpcProtocol)); const extHostModelViewTree = rpcProtocol.set(SqlExtHostContext.ExtHostModelViewTreeViews, new ExtHostModelViewTreeViews(rpcProtocol));
@@ -925,7 +920,7 @@ export function createApiFactory(
}; };
} }
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: ISqlExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> { export function initializeExtensionApi(extensionService: IExtHostExtensionService, apiFactory: ISqlExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider)); return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
} }

View File

@@ -263,12 +263,12 @@ export class CustomTreeView extends Disposable implements ITreeView {
} }
} }
private _message: string | IMarkdownString | undefined; private _message: string | undefined;
get message(): string | IMarkdownString | undefined { get message(): string | undefined {
return this._message; return this._message;
} }
set message(message: string | IMarkdownString | undefined) { set message(message: string | undefined) {
this._message = message; this._message = message;
this.updateMessage(); this.updateMessage();
} }
@@ -746,7 +746,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
const icon = DOM.append(container, DOM.$('.custom-view-tree-node-item-icon')); const icon = DOM.append(container, DOM.$('.custom-view-tree-node-item-icon'));
const resourceLabel = this.labels.create(container, { supportHighlights: true, donotSupportOcticons: true }); const resourceLabel = this.labels.create(container, { supportHighlights: true });
const actionsContainer = DOM.append(resourceLabel.element, DOM.$('.actions')); const actionsContainer = DOM.append(resourceLabel.element, DOM.$('.actions'));
const actionBar = new ActionBar(actionsContainer, { const actionBar = new ActionBar(actionsContainer, {
actionViewItemProvider: this.actionViewItemProvider actionViewItemProvider: this.actionViewItemProvider

View File

@@ -26,7 +26,6 @@
}, },
"types": [ "types": [
"keytar", "keytar",
"minimist",
"mocha", "mocha",
"semver", "semver",
"sinon", "sinon",

View File

@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module '@microsoft/applicationinsights-web' {
export interface IConfig {
instrumentationKey?: string;
endpointUrl?: string;
emitLineDelimitedJson?: boolean;
accountId?: string;
sessionRenewalMs?: number;
sessionExpirationMs?: number;
maxBatchSizeInBytes?: number;
maxBatchInterval?: number;
enableDebug?: boolean;
disableExceptionTracking?: boolean;
disableTelemetry?: boolean;
verboseLogging?: boolean;
diagnosticLogInterval?: number;
samplingPercentage?: number;
autoTrackPageVisitTime?: boolean;
disableAjaxTracking?: boolean;
overridePageViewDuration?: boolean;
maxAjaxCallsPerView?: number;
disableDataLossAnalysis?: boolean;
disableCorrelationHeaders?: boolean;
correlationHeaderExcludedDomains?: string[];
disableFlushOnBeforeUnload?: boolean;
enableSessionStorageBuffer?: boolean;
isCookieUseDisabled?: boolean;
cookieDomain?: string;
isRetryDisabled?: boolean;
url?: string;
isStorageUseDisabled?: boolean;
isBeaconApiDisabled?: boolean;
sdkExtension?: string;
isBrowserLinkTrackingEnabled?: boolean;
appId?: string;
enableCorsCorrelation?: boolean;
}
export interface ISnippet {
config: IConfig;
}
export interface IEventTelemetry {
name: string;
properties?: { [key: string]: string };
measurements?: { [key: string]: number };
}
export class ApplicationInsights {
constructor(config: ISnippet);
loadAppInsights(): void;
trackEvent(data: IEventTelemetry): void;
flush(): void;
}
}

View File

@@ -1,4 +1,4 @@
// Type definitions for Electron 4.2.7 // Type definitions for Electron 4.2.9
// Project: http://electronjs.org/ // Project: http://electronjs.org/
// Definitions by: The Electron Team <https://github.com/electron/electron> // Definitions by: The Electron Team <https://github.com/electron/electron>
// Definitions: https://github.com/electron/electron-typescript-definitions // Definitions: https://github.com/electron/electron-typescript-definitions

92
src/typings/vscode-minimist.d.ts vendored Normal file
View File

@@ -0,0 +1,92 @@
// Type definitions for minimist 1.2.0
// Project: https://github.com/substack/minimist
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>, Necroskillz <https://github.com/Necroskillz>, kamranayub <https://github.com/kamranayub>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/**
* Return an argument object populated with the array arguments from args
*
* @param args An optional argument array (typically `process.argv.slice(2)`)
* @param opts An optional options object to customize the parsing
*/
declare function minimist(args?: string[], opts?: minimist.Opts): minimist.ParsedArgs;
/**
* Return an argument object populated with the array arguments from args. Strongly-typed
* to be the intersect of type T with minimist.ParsedArgs.
*
* @type T The type that will be intersected with minimist.ParsedArgs to represent the argument object
* @param args An optional argument array (typically `process.argv.slice(2)`)
* @param opts An optional options object to customize the parsing
*/
declare function minimist<T>(args?: string[], opts?: minimist.Opts): T & minimist.ParsedArgs;
/**
* Return an argument object populated with the array arguments from args. Strongly-typed
* to be the the type T which should extend minimist.ParsedArgs
*
* @type T The type that extends minimist.ParsedArgs and represents the argument object
* @param args An optional argument array (typically `process.argv.slice(2)`)
* @param opts An optional options object to customize the parsing
*/
declare function minimist<T extends minimist.ParsedArgs>(args?: string[], opts?: minimist.Opts): T;
declare namespace minimist {
export interface Opts {
/**
* A string or array of strings argument names to always treat as strings
*/
string?: string | string[];
/**
* A boolean, string or array of strings to always treat as booleans. If true will treat
* all double hyphenated arguments without equals signs as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`)
*/
boolean?: boolean | string | string[];
/**
* An object mapping string names to strings or arrays of string argument names to use as aliases
*/
alias?: { [key: string]: string | string[] };
/**
* An object mapping string argument names to default values
*/
default?: { [key: string]: any };
/**
* When true, populate argv._ with everything after the first non-option
*/
stopEarly?: boolean;
/**
* A function which is invoked with a command line parameter not defined in the opts
* configuration object. If the function returns false, the unknown option is not added to argv
*/
unknown?: (arg: string) => boolean;
/**
* When true, populate argv._ with everything before the -- and argv['--'] with everything after the --.
* Note that with -- set, parsing for arguments still stops after the `--`.
*/
'--'?: boolean;
}
export interface ParsedArgs {
[arg: string]: any;
/**
* If opts['--'] is true, populated with everything after the --
*/
'--'?: string[];
/**
* Contains all the arguments that didn't have an option associated with them
*/
_: string[];
}
}
declare module "vscode-minimist" {
export = minimist;
}

View File

@@ -56,7 +56,7 @@ class WindowManager {
} }
// --- Fullscreen // --- Fullscreen
private _fullscreen: boolean; private _fullscreen: boolean = false;
private readonly _onDidChangeFullscreen = new Emitter<void>(); private readonly _onDidChangeFullscreen = new Emitter<void>();
public readonly onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event; public readonly onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event;

View File

@@ -50,8 +50,8 @@ interface IDomClassList {
const _manualClassList = new class implements IDomClassList { const _manualClassList = new class implements IDomClassList {
private _lastStart: number; private _lastStart: number = -1;
private _lastEnd: number; private _lastEnd: number = -1;
private _findClassName(node: HTMLElement, className: string): void { private _findClassName(node: HTMLElement, className: string): void {
@@ -1200,7 +1200,7 @@ export function asDomUri(uri: URI): URI {
if (Schemas.vscodeRemote === uri.scheme) { if (Schemas.vscodeRemote === uri.scheme) {
// rewrite vscode-remote-uris to uris of the window location // rewrite vscode-remote-uris to uris of the window location
// so that they can be intercepted by the service worker // so that they can be intercepted by the service worker
return _location.with({ path: '/vscode-resources/fetch', query: `u=${JSON.stringify(uri)}` }); return _location.with({ path: '/vscode-remote', query: JSON.stringify(uri) });
} }
return uri; return uri;
} }

View File

@@ -69,7 +69,7 @@ export class Gesture extends Disposable {
private static INSTANCE: Gesture; private static INSTANCE: Gesture;
private static HOLD_DELAY = 700; private static HOLD_DELAY = 700;
private dispatched: boolean; private dispatched = false;
private targets: HTMLElement[]; private targets: HTMLElement[];
private handle: IDisposable | null; private handle: IDisposable | null;

View File

@@ -37,7 +37,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
_context: any; _context: any;
_action: IAction; _action: IAction;
private _actionRunner: IActionRunner; private _actionRunner!: IActionRunner;
constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) { constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) {
super(); super();
@@ -232,7 +232,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
export class ActionViewItem extends BaseActionViewItem { export class ActionViewItem extends BaseActionViewItem {
protected label: HTMLElement; protected label!: HTMLElement;
protected options: IActionViewItemOptions; protected options: IActionViewItemOptions;
private cssClass?: string; private cssClass?: string;

View File

@@ -77,8 +77,8 @@ export class BreadcrumbsWidget {
private _focusedItemIdx: number = -1; private _focusedItemIdx: number = -1;
private _selectedItemIdx: number = -1; private _selectedItemIdx: number = -1;
private _pendingLayout: IDisposable; private _pendingLayout: IDisposable | undefined;
private _dimension: dom.Dimension; private _dimension: dom.Dimension | undefined;
constructor( constructor(
container: HTMLElement container: HTMLElement

View File

@@ -20,10 +20,12 @@ const GOLDEN_RATIO = {
rightMarginRatio: 0.1909 rightMarginRatio: 0.1909
}; };
function createEmptyView(background: Color): ISplitViewView { function createEmptyView(background: Color | undefined): ISplitViewView {
const element = $('.centered-layout-margin'); const element = $('.centered-layout-margin');
element.style.height = '100%'; element.style.height = '100%';
element.style.backgroundColor = background.toString(); if (background) {
element.style.backgroundColor = background.toString();
}
return { return {
element, element,
@@ -53,7 +55,7 @@ export class CenteredViewLayout implements IDisposable {
private splitView?: SplitView; private splitView?: SplitView;
private width: number = 0; private width: number = 0;
private height: number = 0; private height: number = 0;
private style: ICenteredViewStyles; private style!: ICenteredViewStyles;
private didLayout = false; private didLayout = false;
private emptyViews: ISplitViewView[] | undefined; private emptyViews: ISplitViewView[] | undefined;
private readonly splitViewDisposables = new DisposableStore(); private readonly splitViewDisposables = new DisposableStore();
@@ -132,7 +134,8 @@ export class CenteredViewLayout implements IDisposable {
this.splitView.layout(this.width); this.splitView.layout(this.width);
this.splitView.addView(toSplitViewView(this.view, () => this.height), 0); this.splitView.addView(toSplitViewView(this.view, () => this.height), 0);
this.emptyViews = [createEmptyView(this.style.background), createEmptyView(this.style.background)]; const backgroundColor = this.style ? this.style.background : undefined;
this.emptyViews = [createEmptyView(backgroundColor), createEmptyView(backgroundColor)];
this.splitView.addView(this.emptyViews[0], this.state.leftMarginRatio * this.width, 0); this.splitView.addView(this.emptyViews[0], this.state.leftMarginRatio * this.width, 0);
this.splitView.addView(this.emptyViews[1], this.state.rightMarginRatio * this.width, 2); this.splitView.addView(this.emptyViews[1], this.state.rightMarginRatio * this.width, 2);
} else { } else {

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3.76345L5.80687 11.9351L5.08584 11.8927L1 7.29614L1.76345 6.61752L5.50997 10.8324L14.3214 3L15 3.76345Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3.76345L5.80687 11.9351L5.08584 11.8927L1 7.29614L1.76345 6.61752L5.50997 10.8324L14.3214 3L15 3.76345Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@@ -39,4 +39,24 @@
.hc-black .monaco-custom-checkbox:hover { .hc-black .monaco-custom-checkbox:hover {
background: none; background: none;
} }
.monaco-custom-checkbox.monaco-simple-checkbox {
height: 18px;
width: 18px;
border: 1px solid transparent;
border-radius: 3px;
margin-right: 9px;
margin-left: 0px;
padding: 0px;
opacity: 1;
background-size: 16px !important;
}
.monaco-custom-checkbox.monaco-simple-checkbox.checked {
background: url('check-light.svg') center center no-repeat;
}
.monaco-custom-checkbox.monaco-simple-checkbox.checked {
background: url('check-dark.svg') center center no-repeat;
}

View File

@@ -25,6 +25,12 @@ export interface ICheckboxStyles {
inputActiveOptionBackground?: Color; inputActiveOptionBackground?: Color;
} }
export interface ISimpleCheckboxStyles {
checkboxBackground?: Color;
checkboxBorder?: Color;
checkboxForeground?: Color;
}
const defaultOpts = { const defaultOpts = {
inputActiveOptionBorder: Color.fromHex('#007ACC00'), inputActiveOptionBorder: Color.fromHex('#007ACC00'),
inputActiveOptionBackground: Color.fromHex('#0E639C50') inputActiveOptionBackground: Color.fromHex('#0E639C50')
@@ -32,7 +38,7 @@ const defaultOpts = {
export class CheckboxActionViewItem extends BaseActionViewItem { export class CheckboxActionViewItem extends BaseActionViewItem {
private checkbox: Checkbox; private checkbox!: Checkbox;
private readonly disposables = new DisposableStore(); private readonly disposables = new DisposableStore();
render(container: HTMLElement): void { render(container: HTMLElement): void {
@@ -45,7 +51,7 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
title: this._action.label title: this._action.label
}); });
this.disposables.add(this.checkbox); this.disposables.add(this.checkbox);
this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox.checked, this)); this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox!.checked, this));
this.element.appendChild(this.checkbox.domNode); this.element.appendChild(this.checkbox.domNode);
} }
@@ -174,3 +180,46 @@ export class Checkbox extends Widget {
this.domNode.setAttribute('aria-disabled', String(true)); this.domNode.setAttribute('aria-disabled', String(true));
} }
} }
export class SimpleCheckbox extends Widget {
private checkbox: Checkbox;
private styles: ISimpleCheckboxStyles;
readonly domNode: HTMLElement;
constructor(private title: string, private isChecked: boolean) {
super();
this.checkbox = new Checkbox({ title: this.title, isChecked: this.isChecked, actionClassName: 'monaco-simple-checkbox' });
this.domNode = this.checkbox.domNode;
this.styles = {};
this.checkbox.onChange(() => {
this.applyStyles();
});
}
get checked(): boolean {
return this.checkbox.checked;
}
set checked(newIsChecked: boolean) {
this.checkbox.checked = newIsChecked;
this.applyStyles();
}
style(styles: ISimpleCheckboxStyles): void {
this.styles = styles;
this.applyStyles();
}
protected applyStyles(): void {
this.domNode.style.color = this.styles.checkboxForeground ? this.styles.checkboxForeground.toString() : null;
this.domNode.style.backgroundColor = this.styles.checkboxBackground ? this.styles.checkboxBackground.toString() : null;
this.domNode.style.borderColor = this.styles.checkboxBorder ? this.styles.checkboxBorder.toString() : null;
}
}

View File

@@ -5,7 +5,7 @@
import 'vs/css!./contextview'; import 'vs/css!./contextview';
import * as DOM from 'vs/base/browser/dom'; import * as DOM from 'vs/base/browser/dom';
import { IDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range'; import { Range } from 'vs/base/common/range';
export interface IAnchor { export interface IAnchor {
@@ -100,11 +100,11 @@ export class ContextView extends Disposable {
private static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur']; private static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur'];
private static readonly BUBBLE_DOWN_EVENTS = ['click']; private static readonly BUBBLE_DOWN_EVENTS = ['click'];
private container: HTMLElement | null; private container: HTMLElement | null = null;
private view: HTMLElement; private view: HTMLElement;
private delegate: IDelegate | null; private delegate: IDelegate | null = null;
private toDisposeOnClean: IDisposable | null; private toDisposeOnClean: IDisposable = Disposable.None;
private toDisposeOnSetContainer: IDisposable; private toDisposeOnSetContainer: IDisposable = Disposable.None;
constructor(container: HTMLElement) { constructor(container: HTMLElement) {
super(); super();
@@ -120,7 +120,7 @@ export class ContextView extends Disposable {
setContainer(container: HTMLElement | null): void { setContainer(container: HTMLElement | null): void {
if (this.container) { if (this.container) {
dispose(this.toDisposeOnSetContainer); this.toDisposeOnSetContainer.dispose();
this.container.removeChild(this.view); this.container.removeChild(this.view);
this.container = null; this.container = null;
} }
@@ -159,7 +159,7 @@ export class ContextView extends Disposable {
DOM.show(this.view); DOM.show(this.view);
// Render content // Render content
this.toDisposeOnClean = delegate.render(this.view); this.toDisposeOnClean = delegate.render(this.view) || Disposable.None;
// Set active delegate // Set active delegate
this.delegate = delegate; this.delegate = delegate;
@@ -267,10 +267,7 @@ export class ContextView extends Disposable {
delegate.onHide(data); delegate.onHide(data);
} }
if (this.toDisposeOnClean) { this.toDisposeOnClean.dispose();
this.toDisposeOnClean.dispose();
this.toDisposeOnClean = null;
}
DOM.hide(this.view); DOM.hide(this.view);
} }

View File

@@ -29,7 +29,7 @@ const defaultOpts = {
export class CountBadge { export class CountBadge {
private element: HTMLElement; private element: HTMLElement;
private count: number; private count: number = 0;
private countFormat: string; private countFormat: string;
private titleFormat: string; private titleFormat: string;

View File

@@ -149,6 +149,11 @@
outline-style: solid; outline-style: solid;
} }
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-checkbox-row {
padding: 15px 0px 0px;
display: flex;
}
/** Dialog: Buttons Row */ /** Dialog: Buttons Row */
.monaco-workbench .dialog-box > .dialog-buttons-row { .monaco-workbench .dialog-box > .dialog-buttons-row {
display: flex; display: flex;
@@ -175,4 +180,4 @@
margin: 4px 5px; /* allows button focus outline to be visible */ margin: 4px 5px; /* allows button focus outline to be visible */
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View File

@@ -16,15 +16,23 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';
import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { isMacintosh, isLinux } from 'vs/base/common/platform'; import { isMacintosh, isLinux } from 'vs/base/common/platform';
import { SimpleCheckbox, ISimpleCheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox';
export interface IDialogOptions { export interface IDialogOptions {
cancelId?: number; cancelId?: number;
detail?: string; detail?: string;
checkboxLabel?: string;
checkboxChecked?: boolean;
type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending'; type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
keyEventProcessor?: (event: StandardKeyboardEvent) => void; keyEventProcessor?: (event: StandardKeyboardEvent) => void;
} }
export interface IDialogStyles extends IButtonStyles { export interface IDialogResult {
button: number;
checkboxChecked?: boolean;
}
export interface IDialogStyles extends IButtonStyles, ISimpleCheckboxStyles {
dialogForeground?: Color; dialogForeground?: Color;
dialogBackground?: Color; dialogBackground?: Color;
dialogShadow?: Color; dialogShadow?: Color;
@@ -42,6 +50,7 @@ export class Dialog extends Disposable {
private buttonsContainer: HTMLElement | undefined; private buttonsContainer: HTMLElement | undefined;
private messageDetailElement: HTMLElement | undefined; private messageDetailElement: HTMLElement | undefined;
private iconElement: HTMLElement | undefined; private iconElement: HTMLElement | undefined;
private checkbox: SimpleCheckbox | undefined;
private toolbarContainer: HTMLElement | undefined; private toolbarContainer: HTMLElement | undefined;
private buttonGroup: ButtonGroup | undefined; private buttonGroup: ButtonGroup | undefined;
private styles: IDialogStyles | undefined; private styles: IDialogStyles | undefined;
@@ -68,6 +77,19 @@ export class Dialog extends Disposable {
this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail')); this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message; this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
if (this.options.checkboxLabel) {
const checkboxRowElement = messageContainer.appendChild($('.dialog-checkbox-row'));
this.checkbox = this._register(new SimpleCheckbox(this.options.checkboxLabel, !!this.options.checkboxChecked));
checkboxRowElement.appendChild(this.checkbox.domNode);
const checkboxMessageElement = checkboxRowElement.appendChild($('.dialog-checkbox-message'));
checkboxMessageElement.innerText = this.options.checkboxLabel;
}
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'));
} }
@@ -78,12 +100,12 @@ export class Dialog extends Disposable {
} }
} }
async show(): Promise<number> { async show(): Promise<IDialogResult> {
this.focusToReturn = document.activeElement as HTMLElement; this.focusToReturn = document.activeElement as HTMLElement;
return new Promise<number>((resolve) => { return new Promise<IDialogResult>((resolve) => {
if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) { if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) {
resolve(0); resolve({ button: 0 });
return; return;
} }
@@ -112,7 +134,7 @@ export class Dialog extends Disposable {
this._register(button.onDidClick(e => { this._register(button.onDidClick(e => {
EventHelper.stop(e); EventHelper.stop(e);
resolve(buttonMap[index].index); resolve({ button: buttonMap[index].index, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
})); }));
}); });
@@ -147,7 +169,7 @@ export class Dialog extends Disposable {
const evt = new StandardKeyboardEvent(e); const evt = new StandardKeyboardEvent(e);
if (evt.equals(KeyCode.Escape)) { if (evt.equals(KeyCode.Escape)) {
resolve(this.options.cancelId || 0); resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
} }
})); }));
@@ -187,7 +209,7 @@ export class Dialog extends Disposable {
const actionBar = new ActionBar(this.toolbarContainer, {}); const actionBar = new ActionBar(this.toolbarContainer, {});
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => { const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => {
resolve(this.options.cancelId || 0); resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
return Promise.resolve(); return Promise.resolve();
}); });
@@ -221,6 +243,10 @@ export class Dialog extends Disposable {
if (this.buttonGroup) { if (this.buttonGroup) {
this.buttonGroup.buttons.forEach(button => button.style(style)); this.buttonGroup.buttons.forEach(button => button.style(style));
} }
if (this.checkbox) {
this.checkbox.style(style);
}
} }
} }
} }
@@ -261,4 +287,4 @@ export class Dialog extends Disposable {
return buttonMap; return buttonMap;
} }
} }

View File

@@ -29,7 +29,7 @@ export class BaseDropdown extends ActionRunner {
private boxContainer?: HTMLElement; private boxContainer?: HTMLElement;
private _label?: HTMLElement; private _label?: HTMLElement;
private contents?: HTMLElement; private contents?: HTMLElement;
private visible: boolean; private visible: boolean | undefined;
constructor(container: HTMLElement, options: IBaseDropdownOptions) { constructor(container: HTMLElement, options: IBaseDropdownOptions) {
super(); super();
@@ -109,7 +109,7 @@ export class BaseDropdown extends ActionRunner {
} }
isVisible(): boolean { isVisible(): boolean {
return this.visible; return !!this.visible;
} }
protected onEvent(e: Event, activeElement: HTMLElement): void { protected onEvent(e: Event, activeElement: HTMLElement): void {
@@ -272,7 +272,7 @@ export class DropdownMenu extends BaseDropdown {
export class DropdownMenuActionViewItem extends BaseActionViewItem { export class DropdownMenuActionViewItem extends BaseActionViewItem {
private menuActionsOrProvider: any; private menuActionsOrProvider: any;
private dropdownMenu: DropdownMenu; private dropdownMenu: DropdownMenu | undefined;
private contextMenuProvider: IContextMenuProvider; private contextMenuProvider: IContextMenuProvider;
private actionViewItemProvider?: IActionViewItemProvider; private actionViewItemProvider?: IActionViewItemProvider;
private keybindings?: (action: IAction) => ResolvedKeybinding | undefined; private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
@@ -281,7 +281,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment); constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment); constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) { constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) {
super(null, action); super(null, action);
this.menuActionsOrProvider = menuActionsOrProvider; this.menuActionsOrProvider = menuActionsOrProvider;

View File

@@ -114,7 +114,130 @@ export class FindInput extends Widget {
this.inputValidationErrorBackground = options.inputValidationErrorBackground; this.inputValidationErrorBackground = options.inputValidationErrorBackground;
this.inputValidationErrorForeground = options.inputValidationErrorForeground; this.inputValidationErrorForeground = options.inputValidationErrorForeground;
this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || '', options.history || [], !!options.flexibleHeight); const appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || '';
const appendWholeWordsLabel = options.appendWholeWordsLabel || '';
const appendRegexLabel = options.appendRegexLabel || '';
const history = options.history || [];
const flexibleHeight = !!options.flexibleHeight;
this.domNode = document.createElement('div');
dom.addClass(this.domNode, 'monaco-findInput');
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
placeholder: this.placeholder || '',
ariaLabel: this.label || '',
validationOptions: {
validation: this.validation
},
inputBackground: this.inputBackground,
inputForeground: this.inputForeground,
inputBorder: this.inputBorder,
inputValidationInfoBackground: this.inputValidationInfoBackground,
inputValidationInfoForeground: this.inputValidationInfoForeground,
inputValidationInfoBorder: this.inputValidationInfoBorder,
inputValidationWarningBackground: this.inputValidationWarningBackground,
inputValidationWarningForeground: this.inputValidationWarningForeground,
inputValidationWarningBorder: this.inputValidationWarningBorder,
inputValidationErrorBackground: this.inputValidationErrorBackground,
inputValidationErrorForeground: this.inputValidationErrorForeground,
inputValidationErrorBorder: this.inputValidationErrorBorder,
history,
flexibleHeight
}));
this.regex = this._register(new RegexCheckbox({
appendTitle: appendRegexLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.regex.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.regex.onKeyDown(e => {
this._onRegexKeyDown.fire(e);
}));
this.wholeWords = this._register(new WholeWordsCheckbox({
appendTitle: appendWholeWordsLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.wholeWords.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this.caseSensitive = this._register(new CaseSensitiveCheckbox({
appendTitle: appendCaseSensitiveLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.caseSensitive.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.caseSensitive.onKeyDown(e => {
this._onCaseSensitiveKeyDown.fire(e);
}));
if (this._showOptionButtons) {
const paddingRight = (this.caseSensitive.width() + this.wholeWords.width() + this.regex.width()) + 'px';
this.inputBox.inputElement.style.paddingRight = paddingRight;
if (this.inputBox.mirrorElement) {
this.inputBox.mirrorElement.style.paddingRight = paddingRight;
}
}
// Arrow-Key support to navigate between options
let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode];
this.onkeydown(this.domNode, (event: IKeyboardEvent) => {
if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {
let index = indexes.indexOf(<HTMLElement>document.activeElement);
if (index >= 0) {
let newIndex: number = -1;
if (event.equals(KeyCode.RightArrow)) {
newIndex = (index + 1) % indexes.length;
} else if (event.equals(KeyCode.LeftArrow)) {
if (index === 0) {
newIndex = indexes.length - 1;
} else {
newIndex = index - 1;
}
}
if (event.equals(KeyCode.Escape)) {
indexes[index].blur();
} else if (newIndex >= 0) {
indexes[newIndex].focus();
}
dom.EventHelper.stop(event, true);
}
}
});
let controls = document.createElement('div');
controls.className = 'controls';
controls.style.display = this._showOptionButtons ? 'block' : 'none';
controls.appendChild(this.caseSensitive.domNode);
controls.appendChild(this.wholeWords.domNode);
controls.appendChild(this.regex.domNode);
this.domNode.appendChild(controls);
if (parent) { if (parent) {
parent.appendChild(this.domNode); parent.appendChild(this.domNode);
@@ -270,127 +393,6 @@ export class FindInput extends Widget {
dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions)); dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions));
} }
private buildDomNode(appendCaseSensitiveLabel: string, appendWholeWordsLabel: string, appendRegexLabel: string, history: string[], flexibleHeight: boolean): void {
this.domNode = document.createElement('div');
dom.addClass(this.domNode, 'monaco-findInput');
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
placeholder: this.placeholder || '',
ariaLabel: this.label || '',
validationOptions: {
validation: this.validation
},
inputBackground: this.inputBackground,
inputForeground: this.inputForeground,
inputBorder: this.inputBorder,
inputValidationInfoBackground: this.inputValidationInfoBackground,
inputValidationInfoForeground: this.inputValidationInfoForeground,
inputValidationInfoBorder: this.inputValidationInfoBorder,
inputValidationWarningBackground: this.inputValidationWarningBackground,
inputValidationWarningForeground: this.inputValidationWarningForeground,
inputValidationWarningBorder: this.inputValidationWarningBorder,
inputValidationErrorBackground: this.inputValidationErrorBackground,
inputValidationErrorForeground: this.inputValidationErrorForeground,
inputValidationErrorBorder: this.inputValidationErrorBorder,
history,
flexibleHeight
}));
this.regex = this._register(new RegexCheckbox({
appendTitle: appendRegexLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.regex.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.regex.onKeyDown(e => {
this._onRegexKeyDown.fire(e);
}));
this.wholeWords = this._register(new WholeWordsCheckbox({
appendTitle: appendWholeWordsLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.wholeWords.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this.caseSensitive = this._register(new CaseSensitiveCheckbox({
appendTitle: appendCaseSensitiveLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.caseSensitive.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.caseSensitive.onKeyDown(e => {
this._onCaseSensitiveKeyDown.fire(e);
}));
if (this._showOptionButtons) {
const paddingRight = (this.caseSensitive.width() + this.wholeWords.width() + this.regex.width()) + 'px';
this.inputBox.inputElement.style.paddingRight = paddingRight;
if (this.inputBox.mirrorElement) {
this.inputBox.mirrorElement.style.paddingRight = paddingRight;
}
}
// Arrow-Key support to navigate between options
let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode];
this.onkeydown(this.domNode, (event: IKeyboardEvent) => {
if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {
let index = indexes.indexOf(<HTMLElement>document.activeElement);
if (index >= 0) {
let newIndex: number = -1;
if (event.equals(KeyCode.RightArrow)) {
newIndex = (index + 1) % indexes.length;
} else if (event.equals(KeyCode.LeftArrow)) {
if (index === 0) {
newIndex = indexes.length - 1;
} else {
newIndex = index - 1;
}
}
if (event.equals(KeyCode.Escape)) {
indexes[index].blur();
} else if (newIndex >= 0) {
indexes[newIndex].focus();
}
dom.EventHelper.stop(event, true);
}
}
});
let controls = document.createElement('div');
controls.className = 'controls';
controls.style.display = this._showOptionButtons ? 'block' : 'none';
controls.appendChild(this.caseSensitive.domNode);
controls.appendChild(this.wholeWords.domNode);
controls.appendChild(this.regex.domNode);
this.domNode.appendChild(controls);
}
public validate(): void { public validate(): void {
if (this.inputBox) { if (this.inputBox) {
this.inputBox.validate(); this.inputBox.validate();

View File

@@ -277,6 +277,24 @@ export class Grid<T extends IView = IView> extends Disposable {
this._addView(newView, viewSize, location); this._addView(newView, viewSize, location);
} }
addViewAt(newView: T, size: number | DistributeSizing | InvisibleSizing, location: number[]): void {
if (this.views.has(newView)) {
throw new Error('Can\'t add same view twice');
}
let viewSize: number | GridViewSizing;
if (typeof size === 'number') {
viewSize = size;
} else if (size.type === 'distribute') {
viewSize = GridViewSizing.Distribute;
} else {
viewSize = size;
}
this._addView(newView, viewSize, location);
}
protected _addView(newView: T, size: number | GridViewSizing, location: number[]): void { protected _addView(newView: T, size: number | GridViewSizing, location: number[]): void {
this.views.set(newView, newView.element); this.views.set(newView, newView.element);
this.gridview.addView(newView, size, location); this.gridview.addView(newView, size, location);
@@ -308,6 +326,26 @@ export class Grid<T extends IView = IView> extends Disposable {
} }
} }
moveViewTo(view: T, location: number[]): void {
const sourceLocation = this.getViewLocation(view);
const [sourceParentLocation, from] = tail(sourceLocation);
const [targetParentLocation, to] = tail(location);
if (equals(sourceParentLocation, targetParentLocation)) {
this.gridview.moveView(sourceParentLocation, from, to);
} else {
const size = this.getViewSize(view);
const orientation = getLocationOrientation(this.gridview.orientation, sourceLocation);
const cachedViewSize = this.getViewCachedVisibleSize(view);
const sizing = typeof cachedViewSize === 'undefined'
? (orientation === Orientation.HORIZONTAL ? size.width : size.height)
: Sizing.Invisible(cachedViewSize);
this.removeView(view);
this.addViewAt(view, sizing, location);
}
}
swapViews(from: T, to: T): void { swapViews(from: T, to: T): void {
const fromLocation = this.getViewLocation(from); const fromLocation = this.getViewLocation(from);
const toLocation = this.getViewLocation(to); const toLocation = this.getViewLocation(to);
@@ -319,11 +357,20 @@ export class Grid<T extends IView = IView> extends Disposable {
return this.gridview.resizeView(location, size); return this.gridview.resizeView(location, size);
} }
getViewSize(view: T): IViewSize { getViewSize(view?: T): IViewSize {
if (!view) {
return this.gridview.getViewSize();
}
const location = this.getViewLocation(view); const location = this.getViewLocation(view);
return this.gridview.getViewSize(location); return this.gridview.getViewSize(location);
} }
getViewCachedVisibleSize(view: T): number | undefined {
const location = this.getViewLocation(view);
return this.gridview.getViewCachedVisibleSize(location);
}
maximizeViewSize(view: T): void { maximizeViewSize(view: T): void {
const location = this.getViewLocation(view); const location = this.getViewLocation(view);
this.gridview.maximizeViewSize(location); this.gridview.maximizeViewSize(location);
@@ -373,7 +420,7 @@ export class Grid<T extends IView = IView> extends Disposable {
.map(node => node.view); .map(node => node.view);
} }
private getViewLocation(view: T): number[] { getViewLocation(view: T): number[] {
const element = this.views.get(view); const element = this.views.get(view);
if (!element) { if (!element) {
@@ -422,7 +469,7 @@ export interface ISerializableView extends IView {
} }
export interface IViewDeserializer<T extends ISerializableView> { export interface IViewDeserializer<T extends ISerializableView> {
fromJSON(json: object | null): T; fromJSON(json: any): T;
} }
interface InitialLayoutContext<T extends ISerializableView> { interface InitialLayoutContext<T extends ISerializableView> {
@@ -433,7 +480,7 @@ interface InitialLayoutContext<T extends ISerializableView> {
export interface ISerializedLeafNode { export interface ISerializedLeafNode {
type: 'leaf'; type: 'leaf';
data: object | null; data: any;
size: number; size: number;
visible?: boolean; visible?: boolean;
} }

View File

@@ -11,6 +11,7 @@ import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'
import { $ } from 'vs/base/browser/dom'; import { $ } from 'vs/base/browser/dom';
import { tail2 as tail } from 'vs/base/common/arrays'; import { tail2 as tail } from 'vs/base/common/arrays';
import { Color } from 'vs/base/common/color'; import { Color } from 'vs/base/common/color';
import { clamp } from 'vs/base/common/numbers';
export { Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview'; export { Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview';
export { Orientation } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash';
@@ -277,9 +278,7 @@ class BranchNode implements ISplitView, IDisposable {
throw new Error('Invalid from index'); throw new Error('Invalid from index');
} }
if (to < 0 || to > this.children.length) { to = clamp(to, 0, this.children.length);
throw new Error('Invalid to index');
}
if (from < to) { if (from < to) {
to--; to--;
@@ -300,9 +299,7 @@ class BranchNode implements ISplitView, IDisposable {
throw new Error('Invalid from index'); throw new Error('Invalid from index');
} }
if (to < 0 || to >= this.children.length) { to = clamp(to, 0, this.children.length);
throw new Error('Invalid to index');
}
this.splitview.swapViews(from, to); this.splitview.swapViews(from, to);
[this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash, this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash] = [this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash, this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash]; [this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash, this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash] = [this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash, this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash];
@@ -351,6 +348,7 @@ class BranchNode implements ISplitView, IDisposable {
} }
this.splitview.setViewVisible(index, visible); this.splitview.setViewVisible(index, visible);
this._onDidChange.fire(undefined);
} }
getChildCachedVisibleSize(index: number): number | undefined { getChildCachedVisibleSize(index: number): number | undefined {
@@ -442,9 +440,6 @@ class LeafNode implements ISplitView, IDisposable {
private _size: number = 0; private _size: number = 0;
get size(): number { return this._size; } get size(): number { return this._size; }
private _cachedVisibleSize: number | undefined;
get cachedVisibleSize(): number | undefined { return this._cachedVisibleSize; }
private _orthogonalSize: number; private _orthogonalSize: number;
get orthogonalSize(): number { return this._orthogonalSize; } get orthogonalSize(): number { return this._orthogonalSize; }
@@ -553,12 +548,6 @@ class LeafNode implements ISplitView, IDisposable {
} }
setVisible(visible: boolean): void { setVisible(visible: boolean): void {
if (visible) {
this._cachedVisibleSize = undefined;
} else {
this._cachedVisibleSize = this._size;
}
if (this.view.setVisible) { if (this.view.setVisible) {
this.view.setVisible(visible); this.view.setVisible(visible);
} }
@@ -610,7 +599,7 @@ export class GridView implements IDisposable {
private styles: IGridViewStyles; private styles: IGridViewStyles;
private proportionalLayout: boolean; private proportionalLayout: boolean;
private _root: BranchNode; private _root!: BranchNode;
private onDidSashResetRelay = new Relay<number[]>(); private onDidSashResetRelay = new Relay<number[]>();
readonly onDidSashReset: Event<number[]> = this.onDidSashResetRelay.event; readonly onDidSashReset: Event<number[]> = this.onDidSashResetRelay.event;
@@ -765,6 +754,7 @@ export class GridView implements IDisposable {
const [, parentIndex] = tail(rest); const [, parentIndex] = tail(rest);
const sibling = parent.children[0]; const sibling = parent.children[0];
const isSiblingVisible = parent.isChildVisible(0);
parent.removeChild(0); parent.removeChild(0);
const sizes = grandParent.children.map((_, i) => grandParent.getChildSize(i)); const sizes = grandParent.children.map((_, i) => grandParent.getChildSize(i));
@@ -779,7 +769,8 @@ export class GridView implements IDisposable {
} }
} else { } else {
const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), this.layoutController, sibling.size); const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), this.layoutController, sibling.size);
grandParent.addChild(newSibling, sibling.orthogonalSize, parentIndex); const sizing = isSiblingVisible ? sibling.orthogonalSize : Sizing.Invisible(sibling.orthogonalSize);
grandParent.addChild(newSibling, sizing, parentIndex);
} }
for (let i = 0; i < sizes.length; i++) { for (let i = 0; i < sizes.length; i++) {
@@ -868,11 +859,26 @@ export class GridView implements IDisposable {
} }
} }
getViewSize(location: number[]): IViewSize { getViewSize(location?: number[]): IViewSize {
if (!location) {
return { width: this.root.width, height: this.root.height };
}
const [, node] = this.getNode(location); const [, node] = this.getNode(location);
return { width: node.width, height: node.height }; return { width: node.width, height: node.height };
} }
getViewCachedVisibleSize(location: number[]): number | undefined {
const [rest, index] = tail(location);
const [, parent] = this.getNode(rest);
if (!(parent instanceof BranchNode)) {
throw new Error('Invalid location');
}
return parent.getChildCachedVisibleSize(index);
}
maximizeViewSize(location: number[]): void { maximizeViewSize(location: number[]): void {
const [ancestors, node] = this.getNode(location); const [ancestors, node] = this.getNode(location);
@@ -929,12 +935,13 @@ export class GridView implements IDisposable {
return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height }); return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height });
} }
private _getViews(node: Node, orientation: Orientation, box: Box): GridNode { private _getViews(node: Node, orientation: Orientation, box: Box, cachedVisibleSize?: number): GridNode {
if (node instanceof LeafNode) { if (node instanceof LeafNode) {
return { view: node.view, box, cachedVisibleSize: node.cachedVisibleSize }; return { view: node.view, box, cachedVisibleSize };
} }
const children: GridNode[] = []; const children: GridNode[] = [];
let i = 0;
let offset = 0; let offset = 0;
for (const child of node.children) { for (const child of node.children) {
@@ -942,8 +949,9 @@ export class GridView implements IDisposable {
const childBox: Box = orientation === Orientation.HORIZONTAL const childBox: Box = orientation === Orientation.HORIZONTAL
? { top: box.top, left: box.left + offset, width: child.width, height: box.height } ? { top: box.top, left: box.left + offset, width: child.width, height: box.height }
: { top: box.top + offset, left: box.left, width: box.width, height: child.height }; : { top: box.top + offset, left: box.left, width: box.width, height: child.height };
const cachedVisibleSize = node.getChildCachedVisibleSize(i++);
children.push(this._getViews(child, childOrientation, childBox)); children.push(this._getViews(child, childOrientation, childBox, cachedVisibleSize));
offset += orientation === Orientation.HORIZONTAL ? child.width : child.height; offset += orientation === Orientation.HORIZONTAL ? child.width : child.height;
} }

View File

@@ -12,7 +12,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
export interface IIconLabelCreationOptions { export interface IIconLabelCreationOptions {
supportHighlights?: boolean; supportHighlights?: boolean;
supportDescriptionHighlights?: boolean; supportDescriptionHighlights?: boolean;
donotSupportOcticons?: boolean; supportOcticons?: boolean;
} }
export interface IIconLabelValueOptions { export interface IIconLabelValueOptions {
@@ -100,13 +100,13 @@ export class IconLabel extends Disposable {
this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container')))); this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container'))));
if (options && options.supportHighlights) { if (options && options.supportHighlights) {
this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !options.donotSupportOcticons); this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !!options.supportOcticons);
} else { } else {
this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')))); this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name'))));
} }
if (options && options.supportDescriptionHighlights) { if (options && options.supportDescriptionHighlights) {
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !options.donotSupportOcticons); this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !!options.supportOcticons);
} else { } else {
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')))); this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description'))));
} }

View File

@@ -58,7 +58,12 @@
.monaco-inputbox > .wrapper > textarea.input { .monaco-inputbox > .wrapper > textarea.input {
display: block; display: block;
overflow: hidden; -ms-overflow-style: none; /* IE 10+ */
overflow: -moz-scrollbars-none; /* Firefox */
}
.monaco-inputbox > .wrapper > textarea.input::-webkit-scrollbar {
display: none;
} }
.monaco-inputbox > .wrapper > .mirror { .monaco-inputbox > .wrapper > .mirror {
@@ -116,4 +121,4 @@
background-repeat: no-repeat; background-repeat: no-repeat;
width: 16px; width: 16px;
height: 16px; height: 16px;
} }

View File

@@ -19,6 +19,9 @@ import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { HistoryNavigator } from 'vs/base/common/history'; import { HistoryNavigator } from 'vs/base/common/history';
import { IHistoryNavigationWidget } from 'vs/base/browser/history'; import { IHistoryNavigationWidget } from 'vs/base/browser/history';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { domEvent } from 'vs/base/browser/event';
const $ = dom.$; const $ = dom.$;
@@ -28,6 +31,7 @@ export interface IInputOptions extends IInputBoxStyles {
readonly type?: string; readonly type?: string;
readonly validationOptions?: IInputValidationOptions; readonly validationOptions?: IInputValidationOptions;
readonly flexibleHeight?: boolean; readonly flexibleHeight?: boolean;
readonly flexibleMaxHeight?: number;
readonly actions?: ReadonlyArray<IAction>; readonly actions?: ReadonlyArray<IAction>;
@@ -93,7 +97,6 @@ export class InputBox extends Widget {
private contextViewProvider?: IContextViewProvider; private contextViewProvider?: IContextViewProvider;
element: HTMLElement; element: HTMLElement;
private input: HTMLInputElement; private input: HTMLInputElement;
private mirror: HTMLElement;
private actionbar?: ActionBar; private actionbar?: ActionBar;
private options: IInputOptions; private options: IInputOptions;
private message: IMessage | null; private message: IMessage | null;
@@ -101,7 +104,12 @@ export class InputBox extends Widget {
private ariaLabel: string; private ariaLabel: string;
private validation?: IInputValidator; private validation?: IInputValidator;
private state: 'idle' | 'open' | 'closed' = 'idle'; private state: 'idle' | 'open' | 'closed' = 'idle';
private cachedHeight: number | null;
private mirror: HTMLElement | undefined;
private cachedHeight: number | undefined;
private cachedContentHeight: number | undefined;
private maxHeight: number = Number.POSITIVE_INFINITY;
private scrollableElement: ScrollableElement | undefined;
// {{SQL CARBON EDIT}} - Add showValidationMessage and set inputBackground, inputForeground, and inputBorder as protected // {{SQL CARBON EDIT}} - Add showValidationMessage and set inputBackground, inputForeground, and inputBorder as protected
protected showValidationMessage: boolean; protected showValidationMessage: boolean;
@@ -133,7 +141,6 @@ export class InputBox extends Widget {
this.options = options || Object.create(null); this.options = options || Object.create(null);
mixin(this.options, defaultOpts, false); mixin(this.options, defaultOpts, false);
this.message = null; this.message = null;
this.cachedHeight = null;
this.placeholder = this.options.placeholder || ''; this.placeholder = this.options.placeholder || '';
this.ariaLabel = this.options.ariaLabel || ''; this.ariaLabel = this.options.ariaLabel || '';
@@ -171,8 +178,26 @@ export class InputBox extends Widget {
this.onblur(this.input, () => dom.removeClass(this.element, 'synthetic-focus')); this.onblur(this.input, () => dom.removeClass(this.element, 'synthetic-focus'));
if (this.options.flexibleHeight) { if (this.options.flexibleHeight) {
this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;
this.mirror = dom.append(wrapper, $('div.mirror')); this.mirror = dom.append(wrapper, $('div.mirror'));
this.mirror.innerHTML = '&nbsp;'; this.mirror.innerHTML = '&nbsp;';
this.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });
dom.append(container, this.scrollableElement.getDomNode());
this._register(this.scrollableElement);
// from ScrollableElement to DOM
this._register(this.scrollableElement.onScroll(e => this.input.scrollTop = e.scrollTop));
const onSelectionChange = Event.filter(domEvent(document, 'selectionchange'), () => {
const selection = document.getSelection();
return !!selection && selection.anchorNode === wrapper;
});
// from DOM to ScrollableElement
this._register(onSelectionChange(this.updateScrollDimensions, this));
this._register(this.onDidHeightChange(this.updateScrollDimensions, this));
} else { } else {
this.input.type = this.options.type || 'text'; this.input.type = this.options.type || 'text';
this.input.setAttribute('wrap', 'off'); this.input.setAttribute('wrap', 'off');
@@ -254,7 +279,7 @@ export class InputBox extends Widget {
} }
} }
public get mirrorElement(): HTMLElement { public get mirrorElement(): HTMLElement | undefined {
return this.mirror; return this.mirror;
} }
@@ -274,7 +299,7 @@ export class InputBox extends Widget {
} }
public get height(): number { public get height(): number {
return this.cachedHeight === null ? dom.getTotalHeight(this.element) : this.cachedHeight; return typeof this.cachedHeight === 'number' ? this.cachedHeight : dom.getTotalHeight(this.element);
} }
public focus(): void { public focus(): void {
@@ -325,6 +350,19 @@ export class InputBox extends Widget {
} }
} }
private updateScrollDimensions(): void {
if (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number') {
return;
}
const scrollHeight = this.cachedContentHeight;
const height = this.cachedHeight;
const scrollTop = this.input.scrollTop;
this.scrollableElement!.setScrollDimensions({ scrollHeight, height });
this.scrollableElement!.setScrollPosition({ scrollTop });
}
public showMessage(message: IMessage, force?: boolean): void { public showMessage(message: IMessage, force?: boolean): void {
this.message = message; this.message = message;
@@ -544,12 +582,13 @@ export class InputBox extends Widget {
return; return;
} }
const previousHeight = this.cachedHeight; const previousHeight = this.cachedContentHeight;
this.cachedHeight = dom.getTotalHeight(this.mirror); this.cachedContentHeight = dom.getTotalHeight(this.mirror);
if (previousHeight !== this.cachedHeight) { if (previousHeight !== this.cachedContentHeight) {
this.cachedHeight = Math.min(this.cachedContentHeight, this.maxHeight);
this.input.style.height = this.cachedHeight + 'px'; this.input.style.height = this.cachedHeight + 'px';
this._onDidHeightChange.fire(this.cachedHeight); this._onDidHeightChange.fire(this.cachedContentHeight);
} }
} }

View File

@@ -73,7 +73,7 @@ class PagedRenderer<TElement, TTemplateData> implements IListRenderer<number, IT
export class PagedList<T> implements IDisposable { export class PagedList<T> implements IDisposable {
private list: List<number>; private list: List<number>;
private _model: IPagedModel<T>; private _model!: IPagedModel<T>;
constructor( constructor(
container: HTMLElement, container: HTMLElement,

View File

@@ -57,6 +57,7 @@ export interface IListViewOptions<T> {
readonly mouseSupport?: boolean; readonly mouseSupport?: boolean;
readonly horizontalScrolling?: boolean; readonly horizontalScrolling?: boolean;
readonly ariaProvider?: IAriaProvider<T>; readonly ariaProvider?: IAriaProvider<T>;
readonly additionalScrollHeight?: number;
} }
const DefaultOptions = { const DefaultOptions = {
@@ -163,19 +164,19 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private lastRenderTop: number; private lastRenderTop: number;
private lastRenderHeight: number; private lastRenderHeight: number;
private renderWidth = 0; private renderWidth = 0;
private gesture: Gesture;
private rowsContainer: HTMLElement; private rowsContainer: HTMLElement;
private scrollableElement: ScrollableElement; private scrollableElement: ScrollableElement;
private _scrollHeight: number; private _scrollHeight: number = 0;
private scrollableElementUpdateDisposable: IDisposable | null = null; private scrollableElementUpdateDisposable: IDisposable | null = null;
private scrollableElementWidthDelayer = new Delayer<void>(50); private scrollableElementWidthDelayer = new Delayer<void>(50);
private splicing = false; private splicing = false;
private dragOverAnimationDisposable: IDisposable | undefined; private dragOverAnimationDisposable: IDisposable | undefined;
private dragOverAnimationStopDisposable: IDisposable = Disposable.None; private dragOverAnimationStopDisposable: IDisposable = Disposable.None;
private dragOverMouseY: number; private dragOverMouseY: number = 0;
private setRowLineHeight: boolean; private setRowLineHeight: boolean;
private supportDynamicHeights: boolean; private supportDynamicHeights: boolean;
private horizontalScrolling: boolean; private horizontalScrolling: boolean;
private additionalScrollHeight: number;
private ariaProvider: IAriaProvider<T>; private ariaProvider: IAriaProvider<T>;
private scrollWidth: number | undefined; private scrollWidth: number | undefined;
private canUseTranslate3d: boolean | undefined = undefined; private canUseTranslate3d: boolean | undefined = undefined;
@@ -229,6 +230,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling); this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling); DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling);
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 }; this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 };
this.rowsContainer = document.createElement('div'); this.rowsContainer = document.createElement('div');
@@ -245,7 +248,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.domNode.appendChild(this.scrollableElement.getDomNode()); this.domNode.appendChild(this.scrollableElement.getDomNode());
container.appendChild(this.domNode); container.appendChild(this.domNode);
this.disposables = [this.rangeMap, this.gesture, this.scrollableElement, this.cache]; this.disposables = [this.rangeMap, this.scrollableElement, this.cache];
this.scrollableElement.onScroll(this.onScroll, this, this.disposables); this.scrollableElement.onScroll(this.onScroll, this, this.disposables);
domEvent(this.rowsContainer, TouchEventType.Change)(this.onTouchChange, this, this.disposables); domEvent(this.rowsContainer, TouchEventType.Change)(this.onTouchChange, this, this.disposables);
@@ -689,7 +692,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
} }
get scrollHeight(): number { get scrollHeight(): number {
return this._scrollHeight + (this.horizontalScrolling ? 10 : 0); return this._scrollHeight + (this.horizontalScrolling ? 10 : 0) + this.additionalScrollHeight;
} }
// Events // Events

View File

@@ -519,7 +519,7 @@ const DefaultOpenController: IOpenController = {
export class MouseController<T> implements IDisposable { export class MouseController<T> implements IDisposable {
private multipleSelectionSupport: boolean; private multipleSelectionSupport: boolean;
readonly multipleSelectionController: IMultipleSelectionController<T>; readonly multipleSelectionController: IMultipleSelectionController<T> | undefined;
private openController: IOpenController; private openController: IOpenController;
private mouseSupport: boolean; private mouseSupport: boolean;
private readonly disposables = new DisposableStore(); private readonly disposables = new DisposableStore();
@@ -618,7 +618,7 @@ export class MouseController<T> implements IDisposable {
} }
} }
private onDoubleClick(e: IListMouseEvent<T>): void { protected onDoubleClick(e: IListMouseEvent<T>): void {
if (isInputElement(e.browserEvent.target as HTMLElement)) { if (isInputElement(e.browserEvent.target as HTMLElement)) {
return; return;
} }

View File

@@ -20,22 +20,8 @@ import { Event, Emitter } from 'vs/base/common/event';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { isLinux, isMacintosh } from 'vs/base/common/platform';
function createMenuMnemonicRegExp() { export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
try { export const MENU_ESCAPED_MNEMONIC_REGEX = /(&amp;)?(&amp;)([^\s&])/g;
return new RegExp('\\(&([^\\s&])\\)|(?<!&)&([^\\s&])');
} catch (err) {
return new RegExp('\uFFFF'); // never match please
}
}
export const MENU_MNEMONIC_REGEX = createMenuMnemonicRegExp();
function createMenuEscapedMnemonicRegExp() {
try {
return new RegExp('(?<!&amp;)(?:&amp;)([^\\s&])');
} catch (err) {
return new RegExp('\uFFFF'); // never match please
}
}
export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = createMenuEscapedMnemonicRegExp();
export interface IMenuOptions { export interface IMenuOptions {
context?: any; context?: any;
@@ -369,6 +355,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
protected options: IMenuItemOptions; protected options: IMenuItemOptions;
protected item: HTMLElement; protected item: HTMLElement;
private runOnceToEnableMouseUp: RunOnceScheduler;
private label: HTMLElement; private label: HTMLElement;
private check: HTMLElement; private check: HTMLElement;
private mnemonic: string; private mnemonic: string;
@@ -390,10 +377,24 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
if (label) { if (label) {
let matches = MENU_MNEMONIC_REGEX.exec(label); let matches = MENU_MNEMONIC_REGEX.exec(label);
if (matches) { if (matches) {
this.mnemonic = (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase(); this.mnemonic = (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase();
} }
} }
} }
// Add mouse up listener later to avoid accidental clicks
this.runOnceToEnableMouseUp = new RunOnceScheduler(() => {
if (!this.element) {
return;
}
this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {
EventHelper.stop(e, true);
this.onClick(e);
}));
}, 50);
this._register(this.runOnceToEnableMouseUp);
} }
render(container: HTMLElement): void { render(container: HTMLElement): void {
@@ -425,10 +426,8 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
append(this.item, $('span.keybinding')).textContent = this.options.keybinding; append(this.item, $('span.keybinding')).textContent = this.options.keybinding;
} }
this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => { // Adds mouse up listener to actually run the action
EventHelper.stop(e, true); this.runOnceToEnableMouseUp.schedule();
this.onClick(e);
}));
this.updateClass(); this.updateClass();
this.updateLabel(); this.updateLabel();
@@ -467,9 +466,23 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
const matches = MENU_MNEMONIC_REGEX.exec(label); const matches = MENU_MNEMONIC_REGEX.exec(label);
if (matches) { if (matches) {
label = strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<u aria-hidden="true">$1</u>'); label = strings.escape(label);
// This is global, reset it
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
// We can't use negative lookbehind so if we match our negative and skip
while (escMatch && escMatch[1]) {
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
}
if (escMatch) {
label = `${label.substr(0, escMatch.index)}<u aria-hidden="true">${escMatch[3]}</u>${label.substr(escMatch.index + escMatch[0].length)}`;
}
label = label.replace(/&amp;&amp;/g, '&amp;'); label = label.replace(/&amp;&amp;/g, '&amp;');
this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase()); this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase());
} else { } else {
label = label.replace(/&&/g, '&'); label = label.replace(/&&/g, '&');
} }
@@ -802,7 +815,7 @@ export function cleanMnemonic(label: string): string {
return label; return label;
} }
const mnemonicInText = matches[0].charAt(0) === '&'; const mnemonicInText = !matches[1];
return label.replace(regex, mnemonicInText ? '$2' : '').trim(); return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();
} }

View File

@@ -209,7 +209,7 @@ export class MenuBar extends Disposable {
// Register mnemonics // Register mnemonics
if (mnemonicMatches) { if (mnemonicMatches) {
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2]; let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
this.registerMnemonic(this.menuCache.length, mnemonic); this.registerMnemonic(this.menuCache.length, mnemonic);
} }
@@ -472,15 +472,34 @@ export class MenuBar extends Disposable {
const cleanMenuLabel = cleanMnemonic(label); const cleanMenuLabel = cleanMnemonic(label);
// Update the button label to reflect mnemonics // Update the button label to reflect mnemonics
titleElement.innerHTML = this.options.enableMnemonics ?
strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<mnemonic aria-hidden="true">$1</mnemonic>').replace(/&amp;&amp;/g, '&amp;') : if (this.options.enableMnemonics) {
cleanMenuLabel.replace(/&&/g, '&'); let innerHtml = strings.escape(label);
// This is global so reset it
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
// We can't use negative lookbehind so we match our negative and skip
while (escMatch && escMatch[1]) {
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
}
if (escMatch) {
innerHtml = `${innerHtml.substr(0, escMatch.index)}<mnemonic aria-hidden="true">${escMatch[3]}</mnemonic>${innerHtml.substr(escMatch.index + escMatch[0].length)}`;
}
innerHtml = innerHtml.replace(/&amp;&amp;/g, '&amp;');
titleElement.innerHTML = innerHtml;
} else {
titleElement.innerHTML = cleanMenuLabel.replace(/&&/g, '&');
}
let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label); let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label);
// Register mnemonics // Register mnemonics
if (mnemonicMatches) { if (mnemonicMatches) {
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2]; let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
if (this.options.enableMnemonics) { if (this.options.enableMnemonics) {
buttonElement.setAttribute('aria-keyshortcuts', 'Alt+' + mnemonic.toLocaleLowerCase()); buttonElement.setAttribute('aria-keyshortcuts', 'Alt+' + mnemonic.toLocaleLowerCase());

View File

@@ -61,7 +61,7 @@ export class Sash extends Disposable {
private el: HTMLElement; private el: HTMLElement;
private layoutProvider: ISashLayoutProvider; private layoutProvider: ISashLayoutProvider;
private hidden: boolean; private hidden: boolean;
private orientation: Orientation; private orientation!: Orientation;
private _state: SashState = SashState.Enabled; private _state: SashState = SashState.Enabled;
get state(): SashState { return this._state; } get state(): SashState { return this._state; }

View File

@@ -49,7 +49,7 @@ export abstract class AbstractScrollbar extends Widget {
private _mouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>; private _mouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
public domNode: FastDomNode<HTMLElement>; public domNode: FastDomNode<HTMLElement>;
public slider: FastDomNode<HTMLElement>; public slider!: FastDomNode<HTMLElement>;
protected _shouldRender: boolean; protected _shouldRender: boolean;

View File

@@ -148,9 +148,9 @@ export abstract class AbstractScrollableElement extends Widget {
private readonly _horizontalScrollbar: HorizontalScrollbar; private readonly _horizontalScrollbar: HorizontalScrollbar;
private readonly _domNode: HTMLElement; private readonly _domNode: HTMLElement;
private readonly _leftShadowDomNode: FastDomNode<HTMLElement>; private readonly _leftShadowDomNode: FastDomNode<HTMLElement> | null;
private readonly _topShadowDomNode: FastDomNode<HTMLElement>; private readonly _topShadowDomNode: FastDomNode<HTMLElement> | null;
private readonly _topLeftShadowDomNode: FastDomNode<HTMLElement>; private readonly _topLeftShadowDomNode: FastDomNode<HTMLElement> | null;
private readonly _listenOnDomNode: HTMLElement; private readonly _listenOnDomNode: HTMLElement;
@@ -207,6 +207,10 @@ export abstract class AbstractScrollableElement extends Widget {
this._topLeftShadowDomNode = createFastDomNode(document.createElement('div')); this._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner'); this._topLeftShadowDomNode.setClassName('shadow top-left-corner');
this._domNode.appendChild(this._topLeftShadowDomNode.domNode); this._domNode.appendChild(this._topLeftShadowDomNode.domNode);
} else {
this._leftShadowDomNode = null;
this._topShadowDomNode = null;
this._topLeftShadowDomNode = null;
} }
this._listenOnDomNode = this._options.listenOnDomNode || this._domNode; this._listenOnDomNode = this._options.listenOnDomNode || this._domNode;
@@ -430,9 +434,9 @@ export abstract class AbstractScrollableElement extends Widget {
let enableTop = scrollState.scrollTop > 0; let enableTop = scrollState.scrollTop > 0;
let enableLeft = scrollState.scrollLeft > 0; let enableLeft = scrollState.scrollLeft > 0;
this._leftShadowDomNode.setClassName('shadow' + (enableLeft ? ' left' : '')); this._leftShadowDomNode!.setClassName('shadow' + (enableLeft ? ' left' : ''));
this._topShadowDomNode.setClassName('shadow' + (enableTop ? ' top' : '')); this._topShadowDomNode!.setClassName('shadow' + (enableTop ? ' top' : ''));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : '')); this._topLeftShadowDomNode!.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
} }
} }

View File

@@ -8,7 +8,7 @@ import 'vs/css!./selectBox';
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { Widget } from 'vs/base/browser/ui/widget'; import { Widget } from 'vs/base/browser/ui/widget';
import { Color } from 'vs/base/common/color'; import { Color } from 'vs/base/common/color';
import { deepClone, mixin } from 'vs/base/common/objects'; import { deepClone } from 'vs/base/common/objects';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative'; import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative';
@@ -77,14 +77,11 @@ export class SelectBox extends Widget implements ISelectBoxDelegate {
protected selectBackground?: Color; protected selectBackground?: Color;
protected selectForeground?: Color; protected selectForeground?: Color;
protected selectBorder?: Color; protected selectBorder?: Color;
private styles: ISelectBoxStyles;
private selectBoxDelegate: ISelectBoxDelegate; private selectBoxDelegate: ISelectBoxDelegate;
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) { constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) {
super(); super();
mixin(this.styles, defaultStyles, false);
// Default to native SelectBox for OSX unless overridden // Default to native SelectBox for OSX unless overridden
if (isMacintosh && !(selectBoxOptions && selectBoxOptions.useCustomDrawn)) { if (isMacintosh && !(selectBoxOptions && selectBoxOptions.useCustomDrawn)) {
this.selectBoxDelegate = new SelectBoxNative(options, selected, styles, selectBoxOptions); this.selectBoxDelegate = new SelectBoxNative(options, selected, styles, selectBoxOptions);

View File

@@ -93,23 +93,24 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private _isVisible: boolean; private _isVisible: boolean;
private selectBoxOptions: ISelectBoxOptions; private selectBoxOptions: ISelectBoxOptions;
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
public selectElement: HTMLSelectElement; public selectElement: HTMLSelectElement;
private options: ISelectOptionItem[]; private options: ISelectOptionItem[] = [];
private selected: number; private selected: number;
private readonly _onDidSelect: Emitter<ISelectData>; private readonly _onDidSelect: Emitter<ISelectData>;
private styles: ISelectBoxStyles; private styles: ISelectBoxStyles;
private listRenderer: SelectListRenderer; private listRenderer!: SelectListRenderer;
private contextViewProvider: IContextViewProvider; private contextViewProvider!: IContextViewProvider;
private selectDropDownContainer: HTMLElement; private selectDropDownContainer!: HTMLElement;
private styleElement: HTMLStyleElement; private styleElement!: HTMLStyleElement;
private selectList: List<ISelectOptionItem>; private selectList!: List<ISelectOptionItem>;
private selectDropDownListContainer: HTMLElement; private selectDropDownListContainer!: HTMLElement;
private widthControlElement: HTMLElement; private widthControlElement!: HTMLElement;
private _currentSelection: number; private _currentSelection = 0;
private _dropDownPosition: AnchorPosition; private _dropDownPosition!: AnchorPosition;
private _hasDetails: boolean = false; private _hasDetails: boolean = false;
private selectionDetailsPane: HTMLElement; private selectionDetailsPane!: HTMLElement;
private _skipLayout: boolean = false; private _skipLayout: boolean = false;
private _sticky: boolean = false; // for dev purposes only private _sticky: boolean = false; // for dev purposes only
@@ -247,7 +248,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
} }
public setOptions(options: ISelectOptionItem[], selected?: number): void { public setOptions(options: ISelectOptionItem[], selected?: number): void {
if (!this.options || !arrays.equals(this.options, options)) { if (!arrays.equals(this.options, options)) {
this.options = options; this.options = options;
this.selectElement.options.length = 0; this.selectElement.options.length = 0;
this._hasDetails = false; this._hasDetails = false;
@@ -272,7 +273,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
// Mirror options in drop-down // Mirror options in drop-down
// Populate select list for non-native select mode // Populate select list for non-native select mode
if (this.selectList && !!this.options) { if (this.selectList) {
this.selectList.splice(0, this.selectList.length, this.options); this.selectList.splice(0, this.selectList.length, this.options);
} }
} }
@@ -704,7 +705,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private setWidthControlElement(container: HTMLElement): number { private setWidthControlElement(container: HTMLElement): number {
let elementWidth = 0; let elementWidth = 0;
if (container && !!this.options) { if (container) {
let longest = 0; let longest = 0;
let longestLength = 0; let longestLength = 0;

View File

@@ -17,7 +17,7 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
public selectElement: HTMLSelectElement; public selectElement: HTMLSelectElement;
private selectBoxOptions: ISelectBoxOptions; private selectBoxOptions: ISelectBoxOptions;
private options: ISelectOptionItem[]; private options: ISelectOptionItem[];
private selected: number; private selected = 0;
private readonly _onDidSelect: Emitter<ISelectData>; private readonly _onDidSelect: Emitter<ISelectData>;
private styles: ISelectBoxStyles; private styles: ISelectBoxStyles;

View File

@@ -42,8 +42,8 @@ export abstract class Panel extends Disposable implements IView {
private static readonly HEADER_SIZE = 22; private static readonly HEADER_SIZE = 22;
readonly element: HTMLElement; readonly element: HTMLElement;
private header: HTMLElement; private header!: HTMLElement;
private body: HTMLElement; private body!: HTMLElement;
protected _expanded: boolean; protected _expanded: boolean;
@@ -109,7 +109,7 @@ export abstract class Panel extends Disposable implements IView {
return headerSize + maximumBodySize; return headerSize + maximumBodySize;
} }
width: number; width: number = 0;
constructor(options: IPanelOptions = {}) { constructor(options: IPanelOptions = {}) {
super(); super();
@@ -371,7 +371,7 @@ export class PanelView extends Disposable {
private dndContext: IDndContext = { draggable: null }; private dndContext: IDndContext = { draggable: null };
private el: HTMLElement; private el: HTMLElement;
private panelItems: IPanelItem[] = []; private panelItems: IPanelItem[] = [];
private width: number; private width: number = 0;
private splitview: SplitView; private splitview: SplitView;
private animationTimer: number | undefined = undefined; private animationTimer: number | undefined = undefined;

View File

@@ -72,4 +72,4 @@
.monaco-split-view2.separator-border.vertical > .split-view-container > .split-view-view:not(:first-child)::before { .monaco-split-view2.separator-border.vertical > .split-view-container > .split-view-view:not(:first-child)::before {
height: 1px; height: 1px;
width: 100%; width: 100%;
} }

View File

@@ -79,7 +79,7 @@ abstract class ViewItem {
return typeof this._cachedVisibleSize === 'undefined'; return typeof this._cachedVisibleSize === 'undefined';
} }
set visible(visible: boolean) { setVisible(visible: boolean, size?: number): void {
if (visible === this.visible) { if (visible === this.visible) {
return; return;
} }
@@ -88,7 +88,7 @@ abstract class ViewItem {
this.size = clamp(this._cachedVisibleSize!, this.viewMinimumSize, this.viewMaximumSize); this.size = clamp(this._cachedVisibleSize!, this.viewMinimumSize, this.viewMaximumSize);
this._cachedVisibleSize = undefined; this._cachedVisibleSize = undefined;
} else { } else {
this._cachedVisibleSize = this.size; this._cachedVisibleSize = typeof size === 'number' ? size : this.size;
this.size = 0; this.size = 0;
} }
@@ -125,7 +125,10 @@ abstract class ViewItem {
dom.addClass(container, 'visible'); dom.addClass(container, 'visible');
} }
abstract layout(): void; layout(): void {
this.container.scrollTop = 0;
this.container.scrollLeft = 0;
}
layoutView(orientation: Orientation): void { layoutView(orientation: Orientation): void {
this.view.layout(this.size, orientation); this.view.layout(this.size, orientation);
@@ -140,6 +143,7 @@ abstract class ViewItem {
class VerticalViewItem extends ViewItem { class VerticalViewItem extends ViewItem {
layout(): void { layout(): void {
super.layout();
this.container.style.height = `${this.size}px`; this.container.style.height = `${this.size}px`;
this.layoutView(Orientation.VERTICAL); this.layoutView(Orientation.VERTICAL);
} }
@@ -148,6 +152,7 @@ class VerticalViewItem extends ViewItem {
class HorizontalViewItem extends ViewItem { class HorizontalViewItem extends ViewItem {
layout(): void { layout(): void {
super.layout();
this.container.style.width = `${this.size}px`; this.container.style.width = `${this.size}px`;
this.layoutView(Orientation.HORIZONTAL); this.layoutView(Orientation.HORIZONTAL);
} }
@@ -161,6 +166,7 @@ interface ISashItem {
interface ISashDragSnapState { interface ISashDragSnapState {
readonly index: number; readonly index: number;
readonly limitDelta: number; readonly limitDelta: number;
readonly size: number;
} }
interface ISashDragState { interface ISashDragState {
@@ -203,7 +209,7 @@ export class SplitView extends Disposable {
private proportions: undefined | number[] = undefined; private proportions: undefined | number[] = undefined;
private viewItems: ViewItem[] = []; private viewItems: ViewItem[] = [];
private sashItems: ISashItem[] = []; private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState; private sashDragState: ISashDragState | undefined;
private state: State = State.Idle; private state: State = State.Idle;
private inverseAltBehavior: boolean; private inverseAltBehavior: boolean;
private proportionalLayout: boolean; private proportionalLayout: boolean;
@@ -414,9 +420,10 @@ export class SplitView extends Disposable {
throw new Error('Cant modify splitview'); throw new Error('Cant modify splitview');
} }
const size = this.getViewSize(from); const cachedVisibleSize = this.getViewCachedVisibleSize(from);
const sizing = typeof cachedVisibleSize === 'undefined' ? this.getViewSize(from) : Sizing.Invisible(cachedVisibleSize);
const view = this.removeView(from); const view = this.removeView(from);
this.addView(view, size, to); this.addView(view, sizing, to);
} }
swapViews(from: number, to: number): void { swapViews(from: number, to: number): void {
@@ -452,10 +459,11 @@ export class SplitView extends Disposable {
} }
const viewItem = this.viewItems[index]; const viewItem = this.viewItems[index];
viewItem.visible = visible; viewItem.setVisible(visible);
this.distributeEmptySpace(index); this.distributeEmptySpace(index);
this.layoutViews(); this.layoutViews();
this.saveProportions();
} }
getViewCachedVisibleSize(index: number): number | undefined { getViewCachedVisibleSize(index: number): number | undefined {
@@ -499,8 +507,8 @@ export class SplitView extends Disposable {
// This way, we can press Alt while we resize a sash, macOS style! // This way, we can press Alt while we resize a sash, macOS style!
const disposable = combinedDisposable( const disposable = combinedDisposable(
domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState.current, e.altKey)), domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState!.current, e.altKey)),
domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState.current, false)) domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState!.current, false))
); );
const resetSashDragState = (start: number, alt: boolean) => { const resetSashDragState = (start: number, alt: boolean) => {
@@ -550,7 +558,8 @@ export class SplitView extends Disposable {
snapBefore = { snapBefore = {
index: snapBeforeIndex, index: snapBeforeIndex,
limitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize limitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize,
size: viewItem.size
}; };
} }
@@ -560,7 +569,8 @@ export class SplitView extends Disposable {
snapAfter = { snapAfter = {
index: snapAfterIndex, index: snapAfterIndex,
limitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize limitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize,
size: viewItem.size
}; };
} }
} }
@@ -572,8 +582,8 @@ export class SplitView extends Disposable {
} }
private onSashChange({ current }: ISashEvent): void { private onSashChange({ current }: ISashEvent): void {
const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState; const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState!;
this.sashDragState.current = current; this.sashDragState!.current = current;
const delta = current - start; const delta = current - start;
const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter); const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter);
@@ -596,7 +606,7 @@ export class SplitView extends Disposable {
private onSashEnd(index: number): void { private onSashEnd(index: number): void {
this._onDidSashChange.fire(index); this._onDidSashChange.fire(index);
this.sashDragState.disposable.dispose(); this.sashDragState!.disposable.dispose();
this.saveProportions(); this.saveProportions();
} }
@@ -738,14 +748,14 @@ export class SplitView extends Disposable {
const snapView = this.viewItems[snapBefore.index]; const snapView = this.viewItems[snapBefore.index];
const visible = delta >= snapBefore.limitDelta; const visible = delta >= snapBefore.limitDelta;
snapped = visible !== snapView.visible; snapped = visible !== snapView.visible;
snapView.visible = visible; snapView.setVisible(visible, snapBefore.size);
} }
if (!snapped && snapAfter) { if (!snapped && snapAfter) {
const snapView = this.viewItems[snapAfter.index]; const snapView = this.viewItems[snapAfter.index];
const visible = delta < snapAfter.limitDelta; const visible = delta < snapAfter.limitDelta;
snapped = visible !== snapView.visible; snapped = visible !== snapView.visible;
snapView.visible = visible; snapView.setVisible(visible, snapAfter.size);
} }
if (snapped) { if (snapped) {

View File

@@ -33,7 +33,7 @@ export class ToolBar extends Disposable {
private actionBar: ActionBar; private actionBar: ActionBar;
private toggleMenuAction: ToggleMenuAction; private toggleMenuAction: ToggleMenuAction;
private toggleMenuActionViewItem = this._register(new MutableDisposable<DropdownMenuActionViewItem>()); private toggleMenuActionViewItem = this._register(new MutableDisposable<DropdownMenuActionViewItem>());
private hasSecondaryActions: boolean; private hasSecondaryActions: boolean = false;
private lookupKeybindings: boolean; private lookupKeybindings: boolean;
constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) { constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) {
@@ -162,6 +162,7 @@ class ToggleMenuAction extends Action {
title = title || nls.localize('moreActions', "More Actions..."); title = title || nls.localize('moreActions', "More Actions...");
super(ToggleMenuAction.ID, title, undefined, true); super(ToggleMenuAction.ID, title, undefined, true);
this._menuActions = [];
this.toggleDropdownMenu = toggleDropdownMenu; this.toggleDropdownMenu = toggleDropdownMenu;
} }
@@ -178,4 +179,4 @@ class ToggleMenuAction extends Action {
set menuActions(actions: ReadonlyArray<IAction>) { set menuActions(actions: ReadonlyArray<IAction>) {
this._menuActions = actions; this._menuActions = actions;
} }
} }

View File

@@ -451,8 +451,8 @@ class TypeFilter<T> implements ITreeFilter<T, FuzzyScore>, IDisposable {
private _matchCount = 0; private _matchCount = 0;
get matchCount(): number { return this._matchCount; } get matchCount(): number { return this._matchCount; }
private _pattern: string; private _pattern: string = '';
private _lowercasePattern: string; private _lowercasePattern: string = '';
private disposables: IDisposable[] = []; private disposables: IDisposable[] = [];
set pattern(pattern: string) { set pattern(pattern: string) {
@@ -543,7 +543,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
private _filterOnType: boolean; private _filterOnType: boolean;
get filterOnType(): boolean { return this._filterOnType; } get filterOnType(): boolean { return this._filterOnType; }
private _empty: boolean; private _empty: boolean = false;
get empty(): boolean { return this._empty; } get empty(): boolean { return this._empty; }
private _onDidChangeEmptyState = new Emitter<boolean>(); private _onDidChangeEmptyState = new Emitter<boolean>();
@@ -897,6 +897,7 @@ export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTr
readonly autoExpandSingleChildren?: boolean; readonly autoExpandSingleChildren?: boolean;
readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter; readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;
readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean); readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean);
readonly additionalScrollHeight?: number;
} }
function dfs<T, TFilterData>(node: ITreeNode<T, TFilterData>, fn: (node: ITreeNode<T, TFilterData>) => void): void { function dfs<T, TFilterData>(node: ITreeNode<T, TFilterData>, fn: (node: ITreeNode<T, TFilterData>) => void): void {
@@ -1063,6 +1064,16 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
super.onPointer(e); super.onPointer(e);
} }
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie');
if (onTwistie) {
return;
}
super.onDoubleClick(e);
}
} }
interface ITreeNodeListOptions<T, TFilterData, TRef> extends IListOptions<ITreeNode<T, TFilterData>> { interface ITreeNodeListOptions<T, TFilterData, TRef> extends IListOptions<ITreeNode<T, TFilterData>> {

View File

@@ -238,7 +238,8 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T) e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
) )
), ),
ariaProvider: undefined ariaProvider: undefined,
additionalScrollHeight: options.additionalScrollHeight
}; };
} }

View File

@@ -17,7 +17,7 @@ export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTree
export class CompressedObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<ICompressedTreeNode<T> | null, TFilterData, T | null> { export class CompressedObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<ICompressedTreeNode<T> | null, TFilterData, T | null> {
protected model: CompressedTreeModel<T, TFilterData>; protected model!: CompressedTreeModel<T, TFilterData>;
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<ICompressedTreeNode<T> | null, TFilterData>> { return this.model.onDidChangeCollapseState; } get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<ICompressedTreeNode<T> | null, TFilterData>> { return this.model.onDidChangeCollapseState; }

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