diff --git a/.editorconfig b/.editorconfig
index b4180a87dd7..e7e99b5bcb5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,4 +1,4 @@
-# EditorConfig is awesome: http://EditorConfig.org
+# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
@@ -6,7 +6,6 @@ root = true
# Tab indentation
[*]
indent_style = tab
-indent_size = 4
trim_trailing_whitespace = true
# The indent size used in the `package.json` file cannot be changed
diff --git a/.github/classifier.yml b/.github/classifier.yml
index 85cd5bfe8d7..57392331d24 100644
--- a/.github/classifier.yml
+++ b/.github/classifier.yml
@@ -12,7 +12,7 @@
cli: [],
color-palette: [],
config: [],
- css-less-scss: [ aeschli ],
+ css-less-scss: [],
debug-console: [],
debug: {
assignees: [ isidorn ],
@@ -79,7 +79,7 @@
git: [ joaomoreno ],
grammar: [],
hot-exit: [],
- html: [ aeschli ],
+ html: [],
install-update: [],
integrated-terminal: [ Tyriar ],
integration-test: [],
diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json
index 4274c3c871e..045f91a8246 100644
--- a/build/builtInExtensions.json
+++ b/build/builtInExtensions.json
@@ -31,7 +31,7 @@
},
{
"name": "ms-vscode.references-view",
- "version": "0.0.19",
+ "version": "0.0.21",
"repo": "https://github.com/Microsoft/vscode-reference-view",
"metadata": {
"id": "dc489f46-520d-4556-ae85-1f9eab3c412d",
diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js
index 50258a98fb3..33972ba398b 100644
--- a/build/gulpfile.vscode.linux.js
+++ b/build/gulpfile.vscode.linux.js
@@ -15,6 +15,9 @@ const util = require('./lib/util');
const packageJson = require('../package.json');
const product = require('../product.json');
const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
+const path = require('path');
+const root = path.dirname(__dirname);
+const commit = util.getVersion(root);
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
@@ -197,11 +200,10 @@ function prepareSnapPackage(arch) {
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
- .pipe(replace('@@VERSION@@', `${packageJson.version}-${linuxPackageRevision}`))
+ .pipe(replace('@@VERSION@@', commit.substr(0, 8)))
.pipe(rename('snap/snapcraft.yaml'));
const snapUpdate = gulp.src('resources/linux/snap/snapUpdate.sh', { base: '.' })
- .pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename(`usr/share/${product.applicationName}/snapUpdate.sh`));
const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' })
diff --git a/extensions/git/package.json b/extensions/git/package.json
index ef4385ef3db..14ffdfe40bd 100644
--- a/extensions/git/package.json
+++ b/extensions/git/package.json
@@ -1231,6 +1231,7 @@
},
"git.openDiffOnClick": {
"type": "boolean",
+ "scope": "resource",
"default": true,
"description": "%config.openDiffOnClick%"
}
diff --git a/extensions/git/resources/icons/dark/open-change.svg b/extensions/git/resources/icons/dark/open-change.svg
index e43ba7616c5..6f785c26a5e 100644
--- a/extensions/git/resources/icons/dark/open-change.svg
+++ b/extensions/git/resources/icons/dark/open-change.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/extensions/git/resources/icons/light/open-change.svg b/extensions/git/resources/icons/light/open-change.svg
index e53964f3b81..873b93d8106 100644
--- a/extensions/git/resources/icons/light/open-change.svg
+++ b/extensions/git/resources/icons/light/open-change.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts
index 1b3ed4d2dec..eb128be6609 100644
--- a/extensions/git/src/api/git.d.ts
+++ b/extensions/git/src/api/git.d.ts
@@ -67,6 +67,7 @@ export const enum Status {
DELETED,
UNTRACKED,
IGNORED,
+ INTENT_TO_ADD,
ADDED_BY_US,
ADDED_BY_THEM,
diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts
index 2e83594e45b..c07517aa21b 100755
--- a/extensions/git/src/commands.ts
+++ b/extensions/git/src/commands.ts
@@ -340,6 +340,7 @@ export class CommandCenter {
case Status.MODIFIED:
case Status.UNTRACKED:
case Status.IGNORED:
+ case Status.INTENT_TO_ADD:
const repository = this.model.getRepository(resource.resourceUri);
if (!repository) {
diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts
index d188eea026e..d97fcca9e13 100644
--- a/extensions/git/src/repository.ts
+++ b/extensions/git/src/repository.ts
@@ -94,6 +94,7 @@ export class Resource implements SourceControlResourceState {
case Status.INDEX_COPIED: return Resource.Icons[theme].Copied;
case Status.UNTRACKED: return Resource.Icons[theme].Untracked;
case Status.IGNORED: return Resource.Icons[theme].Ignored;
+ case Status.INTENT_TO_ADD: return Resource.Icons[theme].Added;
case Status.BOTH_DELETED: return Resource.Icons[theme].Conflict;
case Status.ADDED_BY_US: return Resource.Icons[theme].Conflict;
case Status.DELETED_BY_THEM: return Resource.Icons[theme].Conflict;
@@ -116,6 +117,7 @@ export class Resource implements SourceControlResourceState {
case Status.INDEX_COPIED: return localize('index copied', "Index Copied");
case Status.UNTRACKED: return localize('untracked', "Untracked");
case Status.IGNORED: return localize('ignored', "Ignored");
+ case Status.INTENT_TO_ADD: return localize('intent to add', "Intent to Add");
case Status.BOTH_DELETED: return localize('both deleted', "Both Deleted");
case Status.ADDED_BY_US: return localize('added by us', "Added By Us");
case Status.DELETED_BY_THEM: return localize('deleted by them', "Deleted By Them");
@@ -166,6 +168,7 @@ export class Resource implements SourceControlResourceState {
case Status.MODIFIED:
return 'M';
case Status.INDEX_ADDED:
+ case Status.INTENT_TO_ADD:
return 'A';
case Status.INDEX_DELETED:
case Status.DELETED:
@@ -201,6 +204,7 @@ export class Resource implements SourceControlResourceState {
case Status.DELETED:
return new ThemeColor('gitDecoration.deletedResourceForeground');
case Status.INDEX_ADDED:
+ case Status.INTENT_TO_ADD:
return new ThemeColor('gitDecoration.addedResourceForeground');
case Status.INDEX_RENAMED: // todo@joh - special color?
case Status.UNTRACKED:
@@ -1102,7 +1106,8 @@ export class Repository implements Disposable {
const text = lastLine.isEmptyOrWhitespace ? `${textToAppend}\n` : `\n${textToAppend}\n`;
edit.insert(document.uri, lastLine.range.end, text);
- workspace.applyEdit(edit);
+ await workspace.applyEdit(edit);
+ await document.save();
});
}
@@ -1211,9 +1216,27 @@ export class Repository implements Disposable {
}
}
+ private static KnownHugeFolderNames = ['node_modules'];
+
+ private async findKnownHugeFolderPathsToIgnore(): Promise {
+ const folderPaths: string[] = [];
+
+ for (const folderName of Repository.KnownHugeFolderNames) {
+ const folderPath = path.join(this.repository.root, folderName);
+
+ if (await new Promise(c => fs.exists(folderPath, c))) {
+ folderPaths.push(folderPath);
+ }
+ }
+
+ const ignored = await this.checkIgnore(folderPaths);
+
+ return folderPaths.filter(p => !ignored.has(p));
+ }
+
@throttle
private async updateModelState(): Promise {
- const { status, didHitLimit } = await this.repository.getStatus();
+ const { status, didHitLimit } = await this.repository.getStatus(100);
const config = workspace.getConfiguration('git');
const shouldIgnore = config.get('ignoreLimitWarning') === true;
const useIcons = !config.get('decorations.enabled', true);
@@ -1221,15 +1244,34 @@ export class Repository implements Disposable {
this.isRepositoryHuge = didHitLimit;
if (didHitLimit && !shouldIgnore && !this.didWarnAboutLimit) {
+ const knownHugeFolderPaths = await this.findKnownHugeFolderPathsToIgnore();
+ const gitWarn = localize('huge', "The git repository at '{0}' has too many active changes, only a subset of Git features will be enabled.", this.repository.root);
const neverAgain = { title: localize('neveragain', "Don't Show Again") };
- window.showWarningMessage(localize('huge', "The git repository at '{0}' has too many active changes, only a subset of Git features will be enabled.", this.repository.root), neverAgain).then(result => {
+ if (knownHugeFolderPaths.length > 0) {
+ const folderPath = knownHugeFolderPaths[0];
+ const folderName = path.basename(folderPath);
+
+ const addKnown = localize('add known', "Would you like to add '{0}' to .gitignore?", folderName);
+ const yes = { title: localize('yes', "Yes") };
+
+ const result = await window.showWarningMessage(`${gitWarn} ${addKnown}`, yes, neverAgain);
+
+ if (result === neverAgain) {
+ config.update('ignoreLimitWarning', true, false);
+ this.didWarnAboutLimit = true;
+ } else if (result === yes) {
+ this.ignore([Uri.file(folderPath)]);
+ }
+ } else {
+ const result = await window.showWarningMessage(gitWarn, neverAgain);
+
if (result === neverAgain) {
config.update('ignoreLimitWarning', true, false);
}
- });
- this.didWarnAboutLimit = true;
+ this.didWarnAboutLimit = true;
+ }
}
let HEAD: Branch | undefined;
@@ -1287,6 +1329,7 @@ export class Repository implements Disposable {
switch (raw.y) {
case 'M': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.MODIFIED, useIcons, renameUri)); break;
case 'D': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.DELETED, useIcons, renameUri)); break;
+ case 'A': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.INTENT_TO_ADD, useIcons, renameUri)); break;
}
return undefined;
});
diff --git a/extensions/grunt/src/main.ts b/extensions/grunt/src/main.ts
index 38589e8a596..09a812ac06f 100644
--- a/extensions/grunt/src/main.ts
+++ b/extensions/grunt/src/main.ts
@@ -59,6 +59,12 @@ function getOutputChannel(): vscode.OutputChannel {
return _channel;
}
+function showError() {
+ vscode.window.showWarningMessage(localize('gulpTaskDetectError', 'Problem finding jake tasks. See the output for more information.'),
+ localize('jakeShowOutput', 'Go to output')).then(() => {
+ getOutputChannel().show(true);
+ });
+}
interface GruntTaskDefinition extends vscode.TaskDefinition {
task: string;
file?: string;
@@ -120,7 +126,7 @@ class FolderDetector {
let { stdout, stderr } = await exec(commandLine, { cwd: rootPath });
if (stderr) {
getOutputChannel().appendLine(stderr);
- getOutputChannel().show(true);
+ showError();
}
let result: vscode.Task[] = [];
if (stdout) {
@@ -186,7 +192,7 @@ class FolderDetector {
channel.appendLine(err.stdout);
}
channel.appendLine(localize('execFailed', 'Auto detecting Grunt for folder {0} failed with error: {1}', this.workspaceFolder.name, err.error ? err.error.toString() : 'unknown'));
- channel.show(true);
+ showError();
return emptyTasks;
}
}
diff --git a/extensions/html-language-features/.vscode/settings.json b/extensions/html-language-features/.vscode/settings.json
new file mode 100644
index 00000000000..e46111f13be
--- /dev/null
+++ b/extensions/html-language-features/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "editor.insertSpaces": false
+}
\ No newline at end of file
diff --git a/extensions/jake/src/main.ts b/extensions/jake/src/main.ts
index 938ca51bec9..d778dcedab7 100644
--- a/extensions/jake/src/main.ts
+++ b/extensions/jake/src/main.ts
@@ -59,6 +59,13 @@ function getOutputChannel(): vscode.OutputChannel {
return _channel;
}
+function showError() {
+ vscode.window.showWarningMessage(localize('gulpTaskDetectError', 'Problem finding jake tasks. See the output for more information.'),
+ localize('jakeShowOutput', 'Go to output')).then(() => {
+ getOutputChannel().show(true);
+ });
+}
+
interface JakeTaskDefinition extends vscode.TaskDefinition {
task: string;
file?: string;
@@ -124,7 +131,7 @@ class FolderDetector {
let { stdout, stderr } = await exec(commandLine, { cwd: rootPath });
if (stderr) {
getOutputChannel().appendLine(stderr);
- getOutputChannel().show(true);
+ showError();
}
let result: vscode.Task[] = [];
if (stdout) {
@@ -163,7 +170,7 @@ class FolderDetector {
channel.appendLine(err.stdout);
}
channel.appendLine(localize('execFailed', 'Auto detecting Jake for folder {0} failed with error: {1}', this.workspaceFolder.name, err.error ? err.error.toString() : 'unknown'));
- channel.show(true);
+ showError();
return emptyTasks;
}
}
diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
index e1a5a2ee199..d7db7014da3 100644
--- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
+++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5d44152e45a4953fc3b4a0a4e42ea4b97768efa1",
+ "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/de48df22ff31a01f01d28d44f7b3ea79915d8906",
"name": "JavaScript (with React support)",
"scopeName": "source.js",
"patterns": [
@@ -2629,13 +2629,13 @@
]
},
"function-call": {
- "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
- "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
+ "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"name": "meta.function-call.js",
"begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))",
- "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"include": "#literal"
@@ -3664,13 +3664,6 @@
"name": "punctuation.definition.typeparameters.end.js"
}
},
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- "type-parameters-body": {
"patterns": [
{
"include": "#comment"
@@ -3729,33 +3722,6 @@
}
]
},
- "type-parameters-or-type-arguments": {
- "patterns": [
- {
- "name": "meta.type.parameters.js",
- "begin": "(\\<)(?=\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.typeparameters.begin.js"
- }
- },
- "end": "\\>",
- "endCaptures": {
- "0": {
- "name": "punctuation.definition.typeparameters.end.js"
- }
- },
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- {
- "include": "#type-arguments"
- }
- ]
- },
"type": {
"patterns": [
{
@@ -4307,7 +4273,7 @@
"patterns": [
{
"name": "string.template.js",
- "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)`)",
+ "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)",
"beginCaptures": {
"1": {
"name": "entity.name.function.tagged-template.js"
diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json
index 325a2d5193d..abeae4090a9 100644
--- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json
+++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5d44152e45a4953fc3b4a0a4e42ea4b97768efa1",
+ "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/de48df22ff31a01f01d28d44f7b3ea79915d8906",
"name": "JavaScript (with React support)",
"scopeName": "source.js.jsx",
"patterns": [
@@ -2629,13 +2629,13 @@
]
},
"function-call": {
- "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
- "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
+ "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"name": "meta.function-call.js.jsx",
"begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))",
- "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"include": "#literal"
@@ -3664,13 +3664,6 @@
"name": "punctuation.definition.typeparameters.end.js.jsx"
}
},
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- "type-parameters-body": {
"patterns": [
{
"include": "#comment"
@@ -3729,33 +3722,6 @@
}
]
},
- "type-parameters-or-type-arguments": {
- "patterns": [
- {
- "name": "meta.type.parameters.js.jsx",
- "begin": "(\\<)(?=\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.typeparameters.begin.js.jsx"
- }
- },
- "end": "\\>",
- "endCaptures": {
- "0": {
- "name": "punctuation.definition.typeparameters.end.js.jsx"
- }
- },
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- {
- "include": "#type-arguments"
- }
- ]
- },
"type": {
"patterns": [
{
@@ -4307,7 +4273,7 @@
"patterns": [
{
"name": "string.template.js.jsx",
- "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)`)",
+ "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)",
"beginCaptures": {
"1": {
"name": "entity.name.function.tagged-template.js.jsx"
diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json
index 54b289a7d23..c687b41bc5e 100644
--- a/extensions/markdown-language-features/package.json
+++ b/extensions/markdown-language-features/package.json
@@ -305,13 +305,13 @@
"build-preview": "webpack --mode development"
},
"dependencies": {
- "highlight.js": "9.12.0",
- "markdown-it": "^8.4.1",
+ "highlight.js": "9.13.1",
+ "markdown-it": "^8.4.2",
"vscode-extension-telemetry": "0.1.0",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
- "@types/highlight.js": "9.1.10",
+ "@types/highlight.js": "9.12.3",
"@types/lodash.throttle": "^4.1.3",
"@types/markdown-it": "0.0.2",
"@types/node": "^8.10.25",
diff --git a/extensions/markdown-language-features/src/security.ts b/extensions/markdown-language-features/src/security.ts
index 3a62eed2dbd..7f11d65a113 100644
--- a/extensions/markdown-language-features/src/security.ts
+++ b/extensions/markdown-language-features/src/security.ts
@@ -149,6 +149,7 @@ export class PreviewSecuritySelector {
if (selection.type === 'toggle') {
this.cspArbiter.setShouldDisableSecurityWarning(!this.cspArbiter.shouldDisableSecurityWarnings());
+ this.webviewManager.refresh();
return;
} else {
await this.cspArbiter.setSecurityLevelForResource(resource, selection.type);
diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock
index 74030b70a59..071b5b8e161 100644
--- a/extensions/markdown-language-features/yarn.lock
+++ b/extensions/markdown-language-features/yarn.lock
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==
-"@types/highlight.js@9.1.10":
- version "9.1.10"
- resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.1.10.tgz#b621f809cd9573b80992b90cffc5788208e3069c"
- integrity sha512-3uQgLVw3ukDjrgi1h2qxSgsg2W7Sp/BN/P+IBgi8D019FdCcetJzJIxk0Wp1Qfcxzy3EreUnPI7/1HXhFNCRTg==
+"@types/highlight.js@9.12.3":
+ version "9.12.3"
+ resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
+ integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==
"@types/lodash.throttle@^4.1.3":
version "4.1.3"
@@ -2933,10 +2933,10 @@ he@1.1.1:
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
-highlight.js@9.12.0:
- version "9.12.0"
- resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
- integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=
+highlight.js@9.13.1:
+ version "9.13.1"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
+ integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
hmac-drbg@^1.0.0:
version "1.0.1"
@@ -3895,10 +3895,10 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-markdown-it@^8.4.1:
- version "8.4.1"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44"
- integrity sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==
+markdown-it@^8.4.2:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
+ integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
dependencies:
argparse "^1.0.7"
entities "~1.1.1"
diff --git a/extensions/typescript-basics/cgmanifest.json b/extensions/typescript-basics/cgmanifest.json
index 7ff118aafb6..3a7d9edea47 100644
--- a/extensions/typescript-basics/cgmanifest.json
+++ b/extensions/typescript-basics/cgmanifest.json
@@ -6,7 +6,7 @@
"git": {
"name": "TypeScript-TmLanguage",
"repositoryUrl": "https://github.com/Microsoft/TypeScript-TmLanguage",
- "commitHash": "5d44152e45a4953fc3b4a0a4e42ea4b97768efa1"
+ "commitHash": "de48df22ff31a01f01d28d44f7b3ea79915d8906"
}
},
"license": "MIT",
diff --git a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
index 3f5dc77d6e7..5d3637fa75a 100644
--- a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
+++ b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5d44152e45a4953fc3b4a0a4e42ea4b97768efa1",
+ "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/de48df22ff31a01f01d28d44f7b3ea79915d8906",
"name": "TypeScript",
"scopeName": "source.ts",
"patterns": [
@@ -2626,13 +2626,13 @@
]
},
"function-call": {
- "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
- "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
+ "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"name": "meta.function-call.ts",
"begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))",
- "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"include": "#literal"
@@ -3698,13 +3698,6 @@
"name": "punctuation.definition.typeparameters.end.ts"
}
},
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- "type-parameters-body": {
"patterns": [
{
"include": "#comment"
@@ -3763,33 +3756,6 @@
}
]
},
- "type-parameters-or-type-arguments": {
- "patterns": [
- {
- "name": "meta.type.parameters.ts",
- "begin": "(\\<)(?=\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.typeparameters.begin.ts"
- }
- },
- "end": "\\>",
- "endCaptures": {
- "0": {
- "name": "punctuation.definition.typeparameters.end.ts"
- }
- },
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- {
- "include": "#type-arguments"
- }
- ]
- },
"type": {
"patterns": [
{
@@ -4341,7 +4307,7 @@
"patterns": [
{
"name": "string.template.ts",
- "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)`)",
+ "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)",
"beginCaptures": {
"1": {
"name": "entity.name.function.tagged-template.ts"
diff --git a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json
index 67471e8a57b..39311c06db1 100644
--- a/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json
+++ b/extensions/typescript-basics/syntaxes/TypeScriptReact.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5d44152e45a4953fc3b4a0a4e42ea4b97768efa1",
+ "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/de48df22ff31a01f01d28d44f7b3ea79915d8906",
"name": "TypeScriptReact",
"scopeName": "source.tsx",
"patterns": [
@@ -2629,13 +2629,13 @@
]
},
"function-call": {
- "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
- "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
+ "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"name": "meta.function-call.tsx",
"begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))",
- "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)?\\()",
+ "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)?\\()",
"patterns": [
{
"include": "#literal"
@@ -3664,13 +3664,6 @@
"name": "punctuation.definition.typeparameters.end.tsx"
}
},
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- "type-parameters-body": {
"patterns": [
{
"include": "#comment"
@@ -3729,33 +3722,6 @@
}
]
},
- "type-parameters-or-type-arguments": {
- "patterns": [
- {
- "name": "meta.type.parameters.tsx",
- "begin": "(\\<)(?=\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.typeparameters.begin.tsx"
- }
- },
- "end": "\\>",
- "endCaptures": {
- "0": {
- "name": "punctuation.definition.typeparameters.end.tsx"
- }
- },
- "patterns": [
- {
- "include": "#type-parameters-body"
- }
- ]
- },
- {
- "include": "#type-arguments"
- }
- ]
- },
"type": {
"patterns": [
{
@@ -4307,7 +4273,7 @@
"patterns": [
{
"name": "string.template.tsx",
- "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?)*(?\\s*)`)",
+ "begin": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=(<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))(([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer|typeof)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[]|=>|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?))*(?)*(?\\s*)`)",
"beginCaptures": {
"1": {
"name": "entity.name.function.tagged-template.tsx"
diff --git a/package.json b/package.json
index ae650b3bcff..ae21e5bdbba 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
"vscode-ripgrep": "^1.2.5",
"vscode-sqlite3": "4.0.5",
"vscode-textmate": "^4.0.1",
- "vscode-xterm": "3.10.0-beta5",
+ "vscode-xterm": "3.10.0-beta6",
"winreg": "^1.2.4",
"yauzl": "^2.9.1",
"yazl": "^2.4.3"
diff --git a/resources/linux/snap/snapUpdate.sh b/resources/linux/snap/snapUpdate.sh
index d9299ca4d58..77569bfc16a 100755
--- a/resources/linux/snap/snapUpdate.sh
+++ b/resources/linux/snap/snapUpdate.sh
@@ -1,3 +1,3 @@
#!/bin/sh
sleep 2
-@@NAME@@
\ No newline at end of file
+$SNAP_NAME
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 7df35af8038..1d971213754 100644
--- a/src/main.js
+++ b/src/main.js
@@ -175,14 +175,6 @@ function resolveJSFlags(cliArgs, ...jsFlags) {
jsFlags.push(`--max_old_space_size=${cliArgs['max-memory']}`);
}
- // Since Electron 3 we use a V8 version that comes with untrusted code mitigations
- // enabled by default (https://v8.dev/docs/untrusted-code-mitigations). This comes
- // at a performance cost according to the blog. Since we do not execute untrusted
- // code, we disable these mitigations.
- // TODO@Ben revisit this for later Electron versions, search for more usages of
- // --no-untrusted-code-mitigations
- jsFlags.push('--no-untrusted-code-mitigations');
-
return jsFlags.length > 0 ? jsFlags.join(' ') : null;
}
diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json
index 7ea051a4d06..0a4ca61c962 100644
--- a/src/tsconfig.strictNullChecks.json
+++ b/src/tsconfig.strictNullChecks.json
@@ -76,6 +76,7 @@
"./vs/base/browser/ui/toolbar/toolbar.ts",
"./vs/base/browser/ui/tree/abstractTree.ts",
"./vs/base/browser/ui/tree/asyncDataTree.ts",
+ "./vs/base/browser/ui/tree/dataTree.ts",
"./vs/base/browser/ui/tree/indexTree.ts",
"./vs/base/browser/ui/tree/indexTreeModel.ts",
"./vs/base/browser/ui/tree/objectTree.ts",
@@ -98,6 +99,7 @@
"./vs/base/parts/ipc/test/node/testService.ts",
"./vs/base/parts/quickopen/common/quickOpen.ts",
"./vs/base/parts/quickopen/common/quickOpenScorer.ts",
+ "./vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts",
"./vs/base/test/browser/browser.test.ts",
"./vs/base/test/browser/comparers.test.ts",
"./vs/base/test/browser/dom.test.ts",
@@ -105,46 +107,64 @@
"./vs/base/test/browser/progressBar.test.ts",
"./vs/base/test/browser/ui/contextview/contextview.test.ts",
"./vs/base/test/browser/ui/grid/grid.test.ts",
+ "./vs/base/test/browser/ui/grid/gridview.test.ts",
"./vs/base/test/browser/ui/grid/util.ts",
"./vs/base/test/browser/ui/list/listView.test.ts",
"./vs/base/test/browser/ui/list/rangeMap.test.ts",
"./vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts",
"./vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts",
+ "./vs/base/test/browser/ui/splitview/splitview.test.ts",
+ "./vs/base/test/browser/ui/tree/asyncDataTree.test.ts",
"./vs/base/test/browser/ui/tree/indexTreeModel.test.ts",
"./vs/base/test/browser/ui/tree/objectTree.test.ts",
"./vs/base/test/browser/ui/tree/objectTreeModel.test.ts",
+ "./vs/base/test/common/arrays.test.ts",
"./vs/base/test/common/assert.test.ts",
+ "./vs/base/test/common/async.test.ts",
"./vs/base/test/common/cache.test.ts",
"./vs/base/test/common/cancellation.test.ts",
"./vs/base/test/common/charCode.test.ts",
"./vs/base/test/common/collections.test.ts",
"./vs/base/test/common/color.test.ts",
"./vs/base/test/common/decorators.test.ts",
+ "./vs/base/test/common/diff/diff.test.ts",
"./vs/base/test/common/errors.test.ts",
+ "./vs/base/test/common/event.test.ts",
"./vs/base/test/common/filters.perf.test.ts",
"./vs/base/test/common/filters.test.ts",
"./vs/base/test/common/hash.test.ts",
+ "./vs/base/test/common/history.test.ts",
"./vs/base/test/common/json.test.ts",
"./vs/base/test/common/jsonEdit.test.ts",
"./vs/base/test/common/jsonFormatter.test.ts",
+
"./vs/base/test/common/labels.test.ts",
"./vs/base/test/common/lifecycle.test.ts",
"./vs/base/test/common/linkedList.test.ts",
+ "./vs/base/test/common/map.test.ts",
"./vs/base/test/common/marshalling.test.ts",
"./vs/base/test/common/mime.test.ts",
"./vs/base/test/common/objects.test.ts",
+ "./vs/base/test/common/octicon.test.ts",
"./vs/base/test/common/paging.test.ts",
"./vs/base/test/common/paths.test.ts",
"./vs/base/test/common/resources.test.ts",
"./vs/base/test/common/scrollable.test.ts",
+ "./vs/base/test/common/strings.test.ts",
"./vs/base/test/common/types.test.ts",
+ "./vs/base/test/common/uri.test.ts",
"./vs/base/test/common/utils.ts",
"./vs/base/test/common/uuid.test.ts",
+ "./vs/base/test/node/config.test.ts",
"./vs/base/test/node/console.test.ts",
"./vs/base/test/node/decoder.test.ts",
"./vs/base/test/node/encoding/encoding.test.ts",
+ "./vs/base/test/node/extfs/extfs.test.ts",
+ "./vs/base/test/node/flow.test.ts",
"./vs/base/test/node/id.test.ts",
+ "./vs/base/test/node/glob.test.ts",
"./vs/base/test/node/port.test.ts",
+ "./vs/base/test/node/pfs.test.ts",
"./vs/base/test/node/processes/fixtures/fork.ts",
"./vs/base/test/node/processes/fixtures/fork_large.ts",
"./vs/base/test/node/processes/processes.test.ts",
@@ -177,6 +197,7 @@
"./vs/code/node/wait.ts",
"./vs/code/node/windowsFinder.ts",
"./vs/code/test/node/argv.test.ts",
+ "./vs/code/test/node/windowsFinder.test.ts",
"./vs/editor/contrib/bracketMatching/bracketMatching.ts",
"./vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts",
"./vs/editor/contrib/caretOperations/caretOperations.ts",
@@ -204,6 +225,7 @@
"./vs/editor/contrib/comment/comment.ts",
"./vs/editor/contrib/comment/lineCommentCommand.ts",
"./vs/editor/contrib/comment/test/blockCommentCommand.test.ts",
+ "./vs/editor/contrib/comment/test/lineCommentCommand.test.ts",
"./vs/editor/contrib/contextmenu/contextmenu.ts",
"./vs/editor/contrib/cursorUndo/cursorUndo.ts",
"./vs/editor/contrib/dnd/dnd.ts",
@@ -259,6 +281,7 @@
"./vs/editor/contrib/message/messageController.ts",
"./vs/editor/contrib/multicursor/multicursor.ts",
"./vs/editor/contrib/parameterHints/parameterHints.ts",
+ "./vs/editor/contrib/parameterHints/parameterHintsModel.ts",
"./vs/editor/contrib/parameterHints/parameterHintsWidget.ts",
"./vs/editor/contrib/parameterHints/provideSignatureHelp.ts",
"./vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts",
@@ -377,7 +400,6 @@
"./vs/platform/diagnostics/electron-main/diagnosticsService.ts",
"./vs/platform/dialogs/common/dialogs.ts",
"./vs/platform/dialogs/node/dialogIpc.ts",
- "./vs/platform/dialogs/node/dialogService.ts",
"./vs/platform/download/common/download.ts",
"./vs/platform/download/node/downloadIpc.ts",
"./vs/platform/download/node/downloadService.ts",
@@ -606,9 +628,13 @@
"./vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts",
"./vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts",
"./vs/workbench/parts/extensions/test/common/extensionQuery.test.ts",
+ "./vs/workbench/parts/feedback/electron-browser/feedback.contribution.ts",
+ "./vs/workbench/parts/feedback/electron-browser/feedback.ts",
+ "./vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts",
"./vs/workbench/parts/files/common/explorerModel.ts",
"./vs/workbench/parts/files/common/files.ts",
"./vs/workbench/parts/files/electron-browser/views/explorerDecorationsProvider.ts",
+ "./vs/workbench/parts/holidays/electron-browser/holidays.contribution.ts",
"./vs/workbench/parts/localizations/electron-browser/localizationsActions.ts",
"./vs/workbench/parts/logs/common/logConstants.ts",
"./vs/workbench/parts/logs/electron-browser/logs.contribution.ts",
@@ -618,8 +644,8 @@
"./vs/workbench/parts/markers/electron-browser/markersFileDecorations.ts",
"./vs/workbench/parts/markers/electron-browser/markersFilterOptions.ts",
"./vs/workbench/parts/markers/electron-browser/markersModel.ts",
- "./vs/workbench/parts/markers/electron-browser/messages.ts",
"./vs/workbench/parts/markers/electron-browser/markersPanelActions.ts",
+ "./vs/workbench/parts/markers/electron-browser/messages.ts",
"./vs/workbench/parts/outline/electron-browser/outline.ts",
"./vs/workbench/parts/output/common/output.ts",
"./vs/workbench/parts/output/common/outputLinkComputer.ts",
@@ -637,6 +663,7 @@
"./vs/workbench/parts/search/common/constants.ts",
"./vs/workbench/parts/search/common/queryBuilder.ts",
"./vs/workbench/parts/search/common/search.ts",
+ "./vs/workbench/parts/search/test/browser/mockSearchTree.ts",
"./vs/workbench/parts/snippets/electron-browser/configureSnippets.ts",
"./vs/workbench/parts/snippets/electron-browser/snippetCompletionProvider.ts",
"./vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts",
@@ -646,6 +673,7 @@
"./vs/workbench/parts/snippets/test/electron-browser/snippetsRewrite.test.ts",
"./vs/workbench/parts/stats/node/stats.contribution.ts",
"./vs/workbench/parts/stats/node/workspaceStats.ts",
+ "./vs/workbench/parts/stats/test/workspaceStats.test.ts",
"./vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts",
"./vs/workbench/parts/surveys/electron-browser/nps.contribution.ts",
"./vs/workbench/parts/tasks/common/problemCollectors.ts",
@@ -655,8 +683,13 @@
"./vs/workbench/parts/tasks/common/taskSystem.ts",
"./vs/workbench/parts/tasks/common/taskTemplates.ts",
"./vs/workbench/parts/tasks/common/tasks.ts",
+ "./vs/workbench/parts/tasks/electron-browser/jsonSchema_v1.ts",
+ "./vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts",
"./vs/workbench/parts/tasks/electron-browser/jsonSchemaCommon.ts",
"./vs/workbench/parts/tasks/electron-browser/runAutomaticTasks.ts",
+ "./vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts",
+ "./vs/workbench/parts/tasks/node/processTaskSystem.ts",
+ "./vs/workbench/parts/tasks/node/taskConfiguration.ts",
"./vs/workbench/parts/tasks/node/tasks.ts",
"./vs/workbench/parts/tasks/test/common/problemMatcher.test.ts",
"./vs/workbench/parts/terminal/browser/terminalFindWidget.ts",
@@ -756,6 +789,7 @@
"./vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts",
"./vs/workbench/services/keybinding/electron-browser/keybindingService.ts",
"./vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts",
+ "./vs/workbench/services/keybinding/test/windowsKeyboardMapper.test.ts",
"./vs/workbench/services/mode/common/workbenchModeService.ts",
"./vs/workbench/services/notification/common/notificationService.ts",
"./vs/workbench/services/panel/common/panelService.ts",
@@ -800,6 +834,7 @@
"./vs/workbench/services/title/common/titleService.ts",
"./vs/workbench/services/workspace/common/workspaceEditing.ts",
"./vs/workbench/test/common/editor/editorOptions.test.ts",
+ "./vs/workbench/test/common/notifications.test.ts",
"./vs/workbench/test/electron-browser/api/mock.ts"
],
"exclude": [
diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts
index 08d9b2b8ec8..e687780e57c 100644
--- a/src/vs/base/browser/browser.ts
+++ b/src/vs/base/browser/browser.ts
@@ -14,7 +14,7 @@ class WindowManager {
// --- Zoom Level
private _zoomLevel: number = 0;
private _lastZoomLevelChangeTime: number = 0;
- private readonly _onDidChangeZoomLevel: Emitter = new Emitter();
+ private readonly _onDidChangeZoomLevel = new Emitter();
public readonly onDidChangeZoomLevel: Event = this._onDidChangeZoomLevel.event;
public getZoomLevel(): number {
@@ -58,7 +58,7 @@ class WindowManager {
// --- Fullscreen
private _fullscreen: boolean;
- private readonly _onDidChangeFullscreen: Emitter = new Emitter();
+ private readonly _onDidChangeFullscreen = new Emitter();
public readonly onDidChangeFullscreen: Event = this._onDidChangeFullscreen.event;
public setFullscreen(fullscreen: boolean): void {
@@ -75,7 +75,7 @@ class WindowManager {
// --- Accessibility
private _accessibilitySupport = platform.AccessibilitySupport.Unknown;
- private readonly _onDidChangeAccessibilitySupport: Emitter = new Emitter();
+ private readonly _onDidChangeAccessibilitySupport = new Emitter();
public readonly onDidChangeAccessibilitySupport: Event = this._onDidChangeAccessibilitySupport.event;
public setAccessibilitySupport(accessibilitySupport: platform.AccessibilitySupport): void {
diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts
index 752437df1ba..635e5228bf2 100644
--- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts
+++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts
@@ -7,7 +7,7 @@ import 'vs/css!./iconlabel';
import * as dom from 'vs/base/browser/dom';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IMatch } from 'vs/base/common/filters';
-import { IDisposable, combinedDisposable, Disposable } from 'vs/base/common/lifecycle';
+import { Disposable } from 'vs/base/common/lifecycle';
export interface IIconLabelCreationOptions {
supportHighlights?: boolean;
@@ -116,13 +116,7 @@ export class IconLabel extends Disposable {
return this.domNode.element;
}
- onClick(callback: (event: MouseEvent) => void): IDisposable {
- return combinedDisposable([
- dom.addDisposableListener(this.labelDescriptionContainer.element, dom.EventType.CLICK, (e: MouseEvent) => callback(e)),
- ]);
- }
-
- setValue(label?: string, description?: string, options?: IIconLabelValueOptions): void {
+ setLabel(label?: string, description?: string, options?: IIconLabelValueOptions): void {
const classes = ['monaco-icon-label'];
if (options) {
if (options.extraClasses) {
diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts
index ab2113c2cca..e9bfa3fb980 100644
--- a/src/vs/base/browser/ui/menu/menu.ts
+++ b/src/vs/base/browser/ui/menu/menu.ts
@@ -15,7 +15,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Color } from 'vs/base/common/color';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
-import { ScrollbarVisibility } from 'vs/base/common/scrollable';
+import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { Event, Emitter } from 'vs/base/common/event';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
@@ -59,6 +59,7 @@ export class Menu extends ActionBar {
private menuDisposables: IDisposable[];
private scrollableElement: DomScrollableElement;
private menuElement: HTMLElement;
+ private scrollTopHold: number;
private readonly _onScroll: Emitter;
@@ -121,6 +122,7 @@ export class Menu extends ActionBar {
let relatedTarget = e.relatedTarget as HTMLElement;
if (!isAncestor(relatedTarget, this.domNode)) {
this.focusedItem = undefined;
+ this.scrollTopHold = this.menuElement.scrollTop;
this.updateFocus();
e.stopPropagation();
}
@@ -143,6 +145,7 @@ export class Menu extends ActionBar {
if (hasClass(target, 'action-item')) {
const lastFocusedItem = this.focusedItem;
+ this.scrollTopHold = this.menuElement.scrollTop;
this.setFocusedItem(target);
if (lastFocusedItem !== this.focusedItem) {
@@ -178,7 +181,11 @@ export class Menu extends ActionBar {
this._onScroll.fire();
}, this, this.menuDisposables);
- this._register(addDisposableListener(this.menuElement, EventType.SCROLL, (e) => {
+ this._register(addDisposableListener(this.menuElement, EventType.SCROLL, (e: ScrollEvent) => {
+ if (this.scrollTopHold !== undefined) {
+ this.menuElement.scrollTop = this.scrollTopHold;
+ this.scrollTopHold = undefined;
+ }
this.scrollableElement.scanDomNode();
}));
diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts
index a6256deeba9..9b31c847f70 100644
--- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts
+++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts
@@ -281,6 +281,7 @@ export abstract class AbstractScrollableElement extends Widget {
let massagedOptions = resolveOptions(newOptions);
this._options.handleMouseWheel = massagedOptions.handleMouseWheel;
this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity;
+ this._options.fastScrollSensitivity = massagedOptions.fastScrollSensitivity;
this._setListeningToMouseWheel(this._options.handleMouseWheel);
if (!this._options.lazyRender) {
@@ -340,6 +341,12 @@ export abstract class AbstractScrollableElement extends Widget {
deltaY = 0;
}
+ if (e.browserEvent && e.browserEvent.altKey) {
+ // fastScrolling
+ deltaX = deltaX * this._options.fastScrollSensitivity;
+ deltaY = deltaY * this._options.fastScrollSensitivity;
+ }
+
const futureScrollPosition = this._scrollable.getFutureScrollPosition();
let desiredScrollPosition: INewScrollPosition = {};
@@ -540,6 +547,7 @@ function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableEleme
alwaysConsumeMouseWheel: (typeof opts.alwaysConsumeMouseWheel !== 'undefined' ? opts.alwaysConsumeMouseWheel : false),
scrollYToX: (typeof opts.scrollYToX !== 'undefined' ? opts.scrollYToX : false),
mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1),
+ fastScrollSensitivity: (typeof opts.fastScrollSensitivity !== 'undefined' ? opts.fastScrollSensitivity : 5),
mouseWheelSmoothScroll: (typeof opts.mouseWheelSmoothScroll !== 'undefined' ? opts.mouseWheelSmoothScroll : true),
arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11),
diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts
index f8ed7e6fb11..7073bee8cb5 100644
--- a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts
+++ b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts
@@ -50,6 +50,11 @@ export interface ScrollableElementCreationOptions {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
+ /**
+ * FastScrolling mulitplier speed when pressing `Alt`
+ * Defaults to 5.
+ */
+ fastScrollSensitivity?: number;
/**
* Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right).
* Defaults to 11.
@@ -107,6 +112,7 @@ export interface ScrollableElementCreationOptions {
export interface ScrollableElementChangeOptions {
handleMouseWheel?: boolean;
mouseWheelScrollSensitivity?: number;
+ fastScrollSensitivity: number;
}
export interface ScrollableElementResolvedOptions {
@@ -118,6 +124,7 @@ export interface ScrollableElementResolvedOptions {
scrollYToX: boolean;
alwaysConsumeMouseWheel: boolean;
mouseWheelScrollSensitivity: number;
+ fastScrollSensitivity: number;
mouseWheelSmoothScroll: boolean;
arrowSize: number;
listenOnDomNode: HTMLElement | null;
diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts
index 590bdd9d83d..0e19843ff3c 100644
--- a/src/vs/base/browser/ui/splitview/panelview.ts
+++ b/src/vs/base/browser/ui/splitview/panelview.ts
@@ -122,14 +122,16 @@ export abstract class Panel implements IView {
return this._expanded;
}
- setExpanded(expanded: boolean): void {
+ setExpanded(expanded: boolean): boolean {
if (this._expanded === !!expanded) {
- return;
+ return false;
}
this._expanded = !!expanded;
this.updateHeader();
this._onDidChange.fire(expanded ? this.expandedSize : undefined);
+
+ return true;
}
get headerVisible(): boolean {
diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts
index fac68e3b949..b0970cb21bb 100644
--- a/src/vs/base/browser/ui/tree/asyncDataTree.ts
+++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts
@@ -514,6 +514,16 @@ export class AsyncDataTree implements IDisposable
}
private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean): void {
+ let nodeChildren: Map> | undefined;
+
+ if (this.identityProvider) {
+ nodeChildren = new Map();
+
+ for (const child of node.children!) {
+ nodeChildren.set(child.id!, child);
+ }
+ }
+
const children = childrenElements.map>>(element => {
if (!this.identityProvider) {
return {
@@ -527,14 +537,8 @@ export class AsyncDataTree implements IDisposable
};
}
- const nodeChildren = new Map>();
-
- for (const child of node.children!) {
- nodeChildren.set(child.id!, child);
- }
-
const id = this.identityProvider.getId(element).toString();
- const asyncDataTreeNode = nodeChildren.get(id);
+ const asyncDataTreeNode = nodeChildren!.get(id);
if (!asyncDataTreeNode) {
return {
diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts
index 2f628f57b62..f6a4006af84 100644
--- a/src/vs/base/browser/ui/tree/dataTree.ts
+++ b/src/vs/base/browser/ui/tree/dataTree.ts
@@ -20,9 +20,9 @@ export interface IDataTreeViewState {
readonly collapsed: string[];
}
-export class DataTree extends AbstractTree {
+export class DataTree extends AbstractTree {
- protected model: ObjectTreeModel;
+ protected model: ObjectTreeModel;
private input: TInput | undefined;
private identityProvider: IIdentityProvider | undefined;
@@ -76,7 +76,7 @@ export class DataTree extends AbstractTree extends AbstractTree 0) {
- const node = queue.shift();
+ const node = queue.shift()!;
if (node !== root && node.collapsed) {
- collapsed.push(getId(node.element));
+ collapsed.push(getId(node.element!));
}
queue.push(...node.children);
diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts
index 6592e10209d..03306c56029 100644
--- a/src/vs/base/common/filters.ts
+++ b/src/vs/base/common/filters.ts
@@ -476,6 +476,10 @@ function isWhitespaceAtPos(value: string, index: number): boolean {
}
}
+function isUpperCaseAtPos(pos: number, word: string, wordLow: string): boolean {
+ return word[pos] !== wordLow[pos];
+}
+
function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number): boolean {
while (patternPos < patternLen && wordPos < wordLen) {
if (patternLow[patternPos] === wordLow[wordPos]) {
@@ -532,18 +536,19 @@ export function fuzzyScore(pattern: string, patternLow: string, patternPos: numb
for (wordPos = 1; wordPos <= wordLen; wordPos++) {
let score = -1;
- let lowWordChar = wordLow[wordPos - 1];
- if (patternLow[patternPos - 1] === lowWordChar) {
+ if (patternLow[patternPos - 1] === wordLow[wordPos - 1]) {
if (wordPos === (patternPos - patternStartPos)) {
// common prefix: `foobar <-> foobaz`
+ // ^^^^^
if (pattern[patternPos - 1] === word[wordPos - 1]) {
score = 7;
} else {
score = 5;
}
- } else if (lowWordChar !== word[wordPos - 1] && (wordPos === 1 || wordLow[wordPos - 2] === word[wordPos - 2])) {
+ } else if (isUpperCaseAtPos(wordPos - 1, word, wordLow) && (wordPos === 1 || !isUpperCaseAtPos(wordPos - 2, word, wordLow))) {
// hitting upper-case: `foo <-> forOthers`
+ // ^^ ^
if (pattern[patternPos - 1] === word[wordPos - 1]) {
score = 7;
} else {
@@ -551,6 +556,7 @@ export function fuzzyScore(pattern: string, patternLow: string, patternPos: numb
}
} else if (isSeparatorAtPos(wordLow, wordPos - 2) || isWhitespaceAtPos(wordLow, wordPos - 2)) {
// post separator: `foo <-> bar_foo`
+ // ^^^
score = 5;
} else {
diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts
index c8fcc221958..6c46a5a5fd3 100644
--- a/src/vs/base/common/labels.ts
+++ b/src/vs/base/common/labels.ts
@@ -366,7 +366,7 @@ export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean
/**
* Handles mnemonics for buttons. Depending on OS:
- * - Windows: Supported via & character (replace && with &)
+ * - Windows: Supported via & character (replace && with & and & with && for escaping)
* - Linux: Supported via _ character (replace && with _)
* - macOS: Unsupported (replace && with empty string)
*/
@@ -375,7 +375,11 @@ export function mnemonicButtonLabel(label: string): string {
return label.replace(/\(&&\w\)|&&/g, '');
}
- return label.replace(/&&/g, isWindows ? '&' : '_');
+ if (isWindows) {
+ return label.replace(/&&|&/g, m => m === '&' ? '&&' : '&');
+ }
+
+ return label.replace(/&&/g, '_');
}
export function unmnemonicLabel(label: string): string {
diff --git a/src/vs/base/node/flow.ts b/src/vs/base/node/flow.ts
index 6214d738c0a..c1232c2993b 100644
--- a/src/vs/base/node/flow.ts
+++ b/src/vs/base/node/flow.ts
@@ -9,7 +9,7 @@ import * as assert from 'assert';
* Executes the given function (fn) over the given array of items (list) in parallel and returns the resulting errors and results as
* array to the callback (callback). The resulting errors and results are evaluated by calling the provided callback function.
*/
-export function parallel(list: T[], fn: (item: T, callback: (err: Error, result: E) => void) => void, callback: (err: Array | null, result: E[]) => void): void {
+export function parallel(list: T[], fn: (item: T, callback: (err: Error | null, result: E | null) => void) => void, callback: (err: Array | null, result: E[]) => void): void {
let results = new Array(list.length);
let errors = new Array(list.length);
let didErrorOccur = false;
diff --git a/src/vs/base/parts/ipc/node/ipc.cp.ts b/src/vs/base/parts/ipc/node/ipc.cp.ts
index 99bd89dbaf1..2217c707d22 100644
--- a/src/vs/base/parts/ipc/node/ipc.cp.ts
+++ b/src/vs/base/parts/ipc/node/ipc.cp.ts
@@ -196,11 +196,6 @@ export class Client implements IChannelClient, IDisposable {
forkOpts.execArgv = ['--nolazy', '--inspect-brk=' + this.options.debugBrk];
}
- if (!Array.isArray(forkOpts.execArgv)) {
- forkOpts.execArgv = [];
- }
- forkOpts.execArgv.push('--no-untrusted-code-mitigations');
-
this.child = fork(this.modulePath, args, forkOpts);
const onMessageEmitter = new Emitter();
diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts
index 9a2235a92d8..6065b5134c7 100644
--- a/src/vs/base/parts/ipc/node/ipc.net.ts
+++ b/src/vs/base/parts/ipc/node/ipc.net.ts
@@ -239,7 +239,7 @@ export class Client extends IPCClient {
get onClose(): Event { return this.protocol.onClose; }
- constructor(private protocol: Protocol, id: TContext) {
+ constructor(private protocol: Protocol | BufferedProtocol, id: TContext) {
super(protocol, id);
}
@@ -276,3 +276,68 @@ export function connect(hook: any, clientId: string): Promise {
socket.once('error', e);
});
}
+
+/**
+ * Will ensure no messages are lost if there are no event listeners.
+ */
+function createBufferedEvent(source: Event): Event {
+ let emitter: Emitter;
+ let hasListeners = false;
+ let isDeliveringMessages = false;
+ let bufferedMessages: T[] = [];
+
+ const deliverMessages = () => {
+ if (isDeliveringMessages) {
+ return;
+ }
+ isDeliveringMessages = true;
+ while (hasListeners && bufferedMessages.length > 0) {
+ emitter.fire(bufferedMessages.shift());
+ }
+ isDeliveringMessages = false;
+ };
+
+ source((e: T) => {
+ bufferedMessages.push(e);
+ deliverMessages();
+ });
+
+ emitter = new Emitter({
+ onFirstListenerAdd: () => {
+ hasListeners = true;
+ // it is important to deliver these messages after this call, but before
+ // other messages have a chance to be received (to guarantee in order delivery)
+ // that's why we're using here nextTick and not other types of timeouts
+ process.nextTick(deliverMessages);
+ },
+ onLastListenerRemove: () => {
+ hasListeners = false;
+ }
+ });
+
+ return emitter.event;
+}
+
+/**
+ * Will ensure no messages are lost if there are no event listeners.
+ */
+export class BufferedProtocol implements IMessagePassingProtocol {
+
+ private readonly _actual: Protocol;
+ public readonly onMessage: Event;
+ public readonly onClose: Event;
+
+ constructor(actual: Protocol) {
+ this._actual = actual;
+ this.onMessage = createBufferedEvent(this._actual.onMessage);
+ this.onClose = createBufferedEvent(this._actual.onClose);
+ }
+
+ public send(buffer: Buffer): void {
+ this._actual.send(buffer);
+ }
+
+ public end(): void {
+ this._actual.end();
+ }
+}
diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts
index 189f85e4841..132f1207fac 100644
--- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts
+++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts
@@ -468,7 +468,7 @@ class Renderer implements IRenderer {
options.title = entry.getTooltip();
options.descriptionTitle = entry.getDescriptionTooltip() || entry.getDescription(); // tooltip over description because it could overflow
options.descriptionMatches = descriptionHighlights || [];
- data.label.setValue(entry.getLabel(), entry.getDescription(), options);
+ data.label.setLabel(entry.getLabel(), entry.getDescription(), options);
// Meta
data.detail.set(entry.getDetail(), detailHighlights);
diff --git a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts
index 57fb24a9d13..dd317811cee 100644
--- a/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts
+++ b/src/vs/base/parts/quickopen/test/common/quickOpenScorer.test.ts
@@ -29,15 +29,15 @@ const ResourceAccessor = new ResourceAccessorClass();
class NullAccessorClass implements scorer.IItemAccessor {
getItemLabel(resource: URI): string {
- return void 0;
+ return undefined!;
}
getItemDescription(resource: URI): string {
- return void 0;
+ return undefined!;
}
getItemPath(resource: URI): string {
- return void 0;
+ return undefined!;
}
}
@@ -120,52 +120,52 @@ suite('Quick Open Scorer', () => {
// Path Identity
const identityRes = scoreItem(resource, ResourceAccessor.getItemPath(resource), true, ResourceAccessor, cache);
assert.ok(identityRes.score);
- assert.equal(identityRes.descriptionMatch.length, 1);
- assert.equal(identityRes.labelMatch.length, 1);
- assert.equal(identityRes.descriptionMatch[0].start, 0);
- assert.equal(identityRes.descriptionMatch[0].end, ResourceAccessor.getItemDescription(resource).length);
- assert.equal(identityRes.labelMatch[0].start, 0);
- assert.equal(identityRes.labelMatch[0].end, ResourceAccessor.getItemLabel(resource).length);
+ assert.equal(identityRes.descriptionMatch!.length, 1);
+ assert.equal(identityRes.labelMatch!.length, 1);
+ assert.equal(identityRes.descriptionMatch![0].start, 0);
+ assert.equal(identityRes.descriptionMatch![0].end, ResourceAccessor.getItemDescription(resource).length);
+ assert.equal(identityRes.labelMatch![0].start, 0);
+ assert.equal(identityRes.labelMatch![0].end, ResourceAccessor.getItemLabel(resource).length);
// Basename Prefix
const basenamePrefixRes = scoreItem(resource, 'som', true, ResourceAccessor, cache);
assert.ok(basenamePrefixRes.score);
assert.ok(!basenamePrefixRes.descriptionMatch);
- assert.equal(basenamePrefixRes.labelMatch.length, 1);
- assert.equal(basenamePrefixRes.labelMatch[0].start, 0);
- assert.equal(basenamePrefixRes.labelMatch[0].end, 'som'.length);
+ assert.equal(basenamePrefixRes.labelMatch!.length, 1);
+ assert.equal(basenamePrefixRes.labelMatch![0].start, 0);
+ assert.equal(basenamePrefixRes.labelMatch![0].end, 'som'.length);
// Basename Camelcase
const basenameCamelcaseRes = scoreItem(resource, 'sF', true, ResourceAccessor, cache);
assert.ok(basenameCamelcaseRes.score);
assert.ok(!basenameCamelcaseRes.descriptionMatch);
- assert.equal(basenameCamelcaseRes.labelMatch.length, 2);
- assert.equal(basenameCamelcaseRes.labelMatch[0].start, 0);
- assert.equal(basenameCamelcaseRes.labelMatch[0].end, 1);
- assert.equal(basenameCamelcaseRes.labelMatch[1].start, 4);
- assert.equal(basenameCamelcaseRes.labelMatch[1].end, 5);
+ assert.equal(basenameCamelcaseRes.labelMatch!.length, 2);
+ assert.equal(basenameCamelcaseRes.labelMatch![0].start, 0);
+ assert.equal(basenameCamelcaseRes.labelMatch![0].end, 1);
+ assert.equal(basenameCamelcaseRes.labelMatch![1].start, 4);
+ assert.equal(basenameCamelcaseRes.labelMatch![1].end, 5);
// Basename Match
const basenameRes = scoreItem(resource, 'of', true, ResourceAccessor, cache);
assert.ok(basenameRes.score);
assert.ok(!basenameRes.descriptionMatch);
- assert.equal(basenameRes.labelMatch.length, 2);
- assert.equal(basenameRes.labelMatch[0].start, 1);
- assert.equal(basenameRes.labelMatch[0].end, 2);
- assert.equal(basenameRes.labelMatch[1].start, 4);
- assert.equal(basenameRes.labelMatch[1].end, 5);
+ assert.equal(basenameRes.labelMatch!.length, 2);
+ assert.equal(basenameRes.labelMatch![0].start, 1);
+ assert.equal(basenameRes.labelMatch![0].end, 2);
+ assert.equal(basenameRes.labelMatch![1].start, 4);
+ assert.equal(basenameRes.labelMatch![1].end, 5);
// Path Match
const pathRes = scoreItem(resource, 'xyz123', true, ResourceAccessor, cache);
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
- assert.equal(pathRes.labelMatch.length, 1);
- assert.equal(pathRes.labelMatch[0].start, 8);
- assert.equal(pathRes.labelMatch[0].end, 11);
- assert.equal(pathRes.descriptionMatch.length, 1);
- assert.equal(pathRes.descriptionMatch[0].start, 1);
- assert.equal(pathRes.descriptionMatch[0].end, 4);
+ assert.equal(pathRes.labelMatch!.length, 1);
+ assert.equal(pathRes.labelMatch![0].start, 8);
+ assert.equal(pathRes.labelMatch![0].end, 11);
+ assert.equal(pathRes.descriptionMatch!.length, 1);
+ assert.equal(pathRes.descriptionMatch![0].start, 1);
+ assert.equal(pathRes.descriptionMatch![0].end, 4);
// No Match
const noRes = scoreItem(resource, '987', true, ResourceAccessor, cache);
@@ -182,7 +182,7 @@ suite('Quick Open Scorer', () => {
test('scoreItem - invalid input', function () {
- let res = scoreItem(null, null, true, ResourceAccessor, cache);
+ let res = scoreItem(null, null!, true, ResourceAccessor, cache);
assert.equal(res.score, 0);
res = scoreItem(null, 'null', true, ResourceAccessor, cache);
@@ -199,12 +199,12 @@ suite('Quick Open Scorer', () => {
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
- assert.equal(pathRes.labelMatch.length, 1);
- assert.equal(pathRes.labelMatch[0].start, 0);
- assert.equal(pathRes.labelMatch[0].end, 7);
- assert.equal(pathRes.descriptionMatch.length, 1);
- assert.equal(pathRes.descriptionMatch[0].start, 23);
- assert.equal(pathRes.descriptionMatch[0].end, 26);
+ assert.equal(pathRes.labelMatch!.length, 1);
+ assert.equal(pathRes.labelMatch![0].start, 0);
+ assert.equal(pathRes.labelMatch![0].end, 7);
+ assert.equal(pathRes.descriptionMatch!.length, 1);
+ assert.equal(pathRes.descriptionMatch![0].start, 23);
+ assert.equal(pathRes.descriptionMatch![0].end, 26);
});
test('scoreItem - avoid match scattering (bug #36119)', function () {
@@ -214,9 +214,9 @@ suite('Quick Open Scorer', () => {
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
- assert.equal(pathRes.labelMatch.length, 1);
- assert.equal(pathRes.labelMatch[0].start, 0);
- assert.equal(pathRes.labelMatch[0].end, 9);
+ assert.equal(pathRes.labelMatch!.length, 1);
+ assert.equal(pathRes.labelMatch![0].start, 0);
+ assert.equal(pathRes.labelMatch![0].end, 9);
});
test('scoreItem - prefers more compact matches', function () {
@@ -227,12 +227,12 @@ suite('Quick Open Scorer', () => {
const res = scoreItem(resource, 'ad', true, ResourceAccessor, cache);
assert.ok(res.score);
assert.ok(res.descriptionMatch);
- assert.ok(!res.labelMatch.length);
- assert.equal(res.descriptionMatch.length, 2);
- assert.equal(res.descriptionMatch[0].start, 11);
- assert.equal(res.descriptionMatch[0].end, 12);
- assert.equal(res.descriptionMatch[1].start, 13);
- assert.equal(res.descriptionMatch[1].end, 14);
+ assert.ok(!res.labelMatch!.length);
+ assert.equal(res.descriptionMatch!.length, 2);
+ assert.equal(res.descriptionMatch![0].start, 11);
+ assert.equal(res.descriptionMatch![0].end, 12);
+ assert.equal(res.descriptionMatch![1].start, 13);
+ assert.equal(res.descriptionMatch![1].end, 14);
});
test('scoreItem - proper target offset', function () {
@@ -247,9 +247,9 @@ suite('Quick Open Scorer', () => {
const res = scoreItem(resource, 'de', true, ResourceAccessor, cache);
- assert.equal(res.labelMatch.length, 1);
- assert.equal(res.labelMatch[0].start, 1);
- assert.equal(res.labelMatch[0].end, 3);
+ assert.equal(res.labelMatch!.length, 1);
+ assert.equal(res.labelMatch![0].start, 1);
+ assert.equal(res.labelMatch![0].end, 3);
});
test('scoreItem - proper target offset #3', function () {
@@ -257,19 +257,19 @@ suite('Quick Open Scorer', () => {
const res = scoreItem(resource, 'debug', true, ResourceAccessor, cache);
- assert.equal(res.descriptionMatch.length, 3);
- assert.equal(res.descriptionMatch[0].start, 9);
- assert.equal(res.descriptionMatch[0].end, 10);
- assert.equal(res.descriptionMatch[1].start, 36);
- assert.equal(res.descriptionMatch[1].end, 37);
- assert.equal(res.descriptionMatch[2].start, 40);
- assert.equal(res.descriptionMatch[2].end, 41);
+ assert.equal(res.descriptionMatch!.length, 3);
+ assert.equal(res.descriptionMatch![0].start, 9);
+ assert.equal(res.descriptionMatch![0].end, 10);
+ assert.equal(res.descriptionMatch![1].start, 36);
+ assert.equal(res.descriptionMatch![1].end, 37);
+ assert.equal(res.descriptionMatch![2].start, 40);
+ assert.equal(res.descriptionMatch![2].end, 41);
- assert.equal(res.labelMatch.length, 2);
- assert.equal(res.labelMatch[0].start, 9);
- assert.equal(res.labelMatch[0].end, 10);
- assert.equal(res.labelMatch[1].start, 20);
- assert.equal(res.labelMatch[1].end, 21);
+ assert.equal(res.labelMatch!.length, 2);
+ assert.equal(res.labelMatch![0].start, 9);
+ assert.equal(res.labelMatch![0].end, 10);
+ assert.equal(res.labelMatch![1].start, 20);
+ assert.equal(res.labelMatch![1].end, 21);
});
test('scoreItem - no match unless query contained in sequence', function () {
diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts
index 1ccb257ae35..1c96a2627e4 100644
--- a/src/vs/base/parts/tree/browser/treeView.ts
+++ b/src/vs/base/parts/tree/browser/treeView.ts
@@ -454,13 +454,13 @@ export class TreeView extends HeightMap {
private highlightedItemWasDraggable: boolean;
private onHiddenScrollTop: number;
- private readonly _onDOMFocus: Emitter = new Emitter();
+ private readonly _onDOMFocus = new Emitter();
get onDOMFocus(): Event { return this._onDOMFocus.event; }
- private readonly _onDOMBlur: Emitter = new Emitter();
+ private readonly _onDOMBlur = new Emitter();
get onDOMBlur(): Event { return this._onDOMBlur.event; }
- private readonly _onDidScroll: Emitter = new Emitter();
+ private readonly _onDidScroll = new Emitter();
get onDidScroll(): Event { return this._onDidScroll.event; }
constructor(context: _.ITreeContext, container: HTMLElement) {
diff --git a/src/vs/base/test/browser/ui/grid/gridview.test.ts b/src/vs/base/test/browser/ui/grid/gridview.test.ts
index 3485fa63b31..3d000d85a67 100644
--- a/src/vs/base/test/browser/ui/grid/gridview.test.ts
+++ b/src/vs/base/test/browser/ui/grid/gridview.test.ts
@@ -21,10 +21,6 @@ suite('Gridview', function () {
container.appendChild(gridview.element);
});
- teardown(function () {
- gridview = null;
- });
-
test('empty gridview is empty', function () {
assert.deepEqual(nodesToArrays(gridview.getViews()), []);
gridview.dispose();
diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts
index 185c9f25aa4..8ca22616e41 100644
--- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts
+++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts
@@ -72,13 +72,9 @@ suite('Splitview', () => {
container.style.height = `${200}px`;
});
- teardown(() => {
- container = null;
- });
-
test('empty splitview has empty DOM', () => {
const splitview = new SplitView(container);
- assert.equal(container.firstElementChild.firstElementChild.childElementCount, 0, 'split view should be empty');
+ assert.equal(container.firstElementChild!.firstElementChild!.childElementCount, 0, 'split view should be empty');
splitview.dispose();
});
diff --git a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
index 670254527a5..7e0fc7b847f 100644
--- a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
+++ b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
@@ -53,7 +53,7 @@ suite('AsyncDataTree', function () {
const dataSource = new class implements IAsyncDataSource {
hasChildren(element: Element): boolean {
- return element.children && element.children.length > 0;
+ return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise {
return Promise.resolve(element.children || []);
@@ -91,14 +91,14 @@ suite('AsyncDataTree', function () {
{ id: 'ac' }
];
- await tree.refresh(null);
+ await tree.refresh(root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
await tree.expand(_('a'));
assert.equal(container.querySelectorAll('.monaco-list-row').length, 4);
_('a').children = [];
- await tree.refresh(null);
+ await tree.refresh(root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
});
});
\ No newline at end of file
diff --git a/src/vs/base/test/common/arrays.test.ts b/src/vs/base/test/common/arrays.test.ts
index dbc2162bc1d..38a235ea871 100644
--- a/src/vs/base/test/common/arrays.test.ts
+++ b/src/vs/base/test/common/arrays.test.ts
@@ -262,7 +262,7 @@ suite('Arrays', () => {
}
test('coalesce', () => {
- let a = arrays.coalesce([null, 1, null, 2, 3]);
+ let a: Array = arrays.coalesce([null, 1, null, 2, 3]);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
assert.equal(a[1], 2);
@@ -298,7 +298,7 @@ suite('Arrays', () => {
});
test('coalesce - inplace', function () {
- let a = [null, 1, null, 2, 3];
+ let a: Array = [null, 1, null, 2, 3];
arrays.coalesceInPlace(a);
assert.equal(a.length, 3);
assert.equal(a[0], 1);
diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts
index 76257d43640..f354e5edc22 100644
--- a/src/vs/base/test/common/async.test.ts
+++ b/src/vs/base/test/common/async.test.ts
@@ -522,7 +522,7 @@ suite('Async', () => {
assert.ok(r2Queue);
assert.equal(r1Queue, queue.queueFor(URI.file('/some/path'))); // same queue returned
- let syncPromiseFactory = () => Promise.resolve(null);
+ let syncPromiseFactory = () => Promise.resolve(undefined);
r1Queue.queue(syncPromiseFactory);
diff --git a/src/vs/base/test/common/diff/diff.test.ts b/src/vs/base/test/common/diff/diff.test.ts
index 70fe3acb597..3628f1e53e3 100644
--- a/src/vs/base/test/common/diff/diff.test.ts
+++ b/src/vs/base/test/common/diff/diff.test.ts
@@ -21,7 +21,7 @@ class StringDiffSequence implements ISequence {
}
function createArray(length: number, value: T): T[] {
- var r = [];
+ const r: T[] = [];
for (var i = 0; i < length; i++) {
r[i] = value;
}
diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts
index 35bae3206a9..b042b60fe83 100644
--- a/src/vs/base/test/common/event.test.ts
+++ b/src/vs/base/test/common/event.test.ts
@@ -71,7 +71,7 @@ suite('Event', function () {
// unhook listener
while (bucket.length) {
- bucket.pop().dispose();
+ bucket.pop()!.dispose();
}
// noop
diff --git a/src/vs/base/test/common/history.test.ts b/src/vs/base/test/common/history.test.ts
index b5d274656fb..9c93a0adeb5 100644
--- a/src/vs/base/test/common/history.test.ts
+++ b/src/vs/base/test/common/history.test.ts
@@ -113,8 +113,8 @@ suite('History Navigator', () => {
assert.equal(testObject.current(), undefined);
});
- function toArray(historyNavigator: HistoryNavigator): string[] {
- let result: string[] = [];
+ function toArray(historyNavigator: HistoryNavigator): Array {
+ let result: Array = [];
historyNavigator.first();
if (historyNavigator.current()) {
do {
diff --git a/src/vs/base/test/common/labels.test.ts b/src/vs/base/test/common/labels.test.ts
index fa619b4780b..a3e54c16232 100644
--- a/src/vs/base/test/common/labels.test.ts
+++ b/src/vs/base/test/common/labels.test.ts
@@ -164,4 +164,19 @@ suite('Labels', () => {
assert.equal(labels.getBaseLabel('c:\\some\\folder\\file.txt'), 'file.txt');
assert.equal(labels.getBaseLabel('c:\\some\\folder'), 'folder');
});
+
+ test('mnemonicButtonLabel', () => {
+ assert.equal(labels.mnemonicButtonLabel('Hello World'), 'Hello World');
+ assert.equal(labels.mnemonicButtonLabel(''), '');
+ if (platform.isWindows) {
+ assert.equal(labels.mnemonicButtonLabel('Hello & World'), 'Hello && World');
+ assert.equal(labels.mnemonicButtonLabel('Do &¬ Save & Continue'), 'Do ¬ Save && Continue');
+ } else if (platform.isMacintosh) {
+ assert.equal(labels.mnemonicButtonLabel('Hello & World'), 'Hello & World');
+ assert.equal(labels.mnemonicButtonLabel('Do &¬ Save & Continue'), 'Do not Save & Continue');
+ } else {
+ assert.equal(labels.mnemonicButtonLabel('Hello & World'), 'Hello & World');
+ assert.equal(labels.mnemonicButtonLabel('Do &¬ Save & Continue'), 'Do _not Save & Continue');
+ }
+ });
});
\ No newline at end of file
diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts
index 25c41d54daa..c179bdb34db 100644
--- a/src/vs/base/test/common/map.test.ts
+++ b/src/vs/base/test/common/map.test.ts
@@ -140,7 +140,7 @@ suite('Map', () => {
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [3, 4, 5, 6, 7]);
let values: number[] = [];
- [3, 4, 5, 6, 7].forEach(key => values.push(cache.get(key)));
+ [3, 4, 5, 6, 7].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [3, 4, 5, 6, 7]);
});
@@ -155,7 +155,7 @@ suite('Map', () => {
cache.peek(4);
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
let values: number[] = [];
- [1, 2, 3, 4, 5].forEach(key => values.push(cache.get(key)));
+ [1, 2, 3, 4, 5].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [1, 2, 3, 4, 5]);
});
@@ -177,7 +177,7 @@ suite('Map', () => {
assert.deepEqual(cache.size, 15);
let values: number[] = [];
for (let i = 6; i <= 20; i++) {
- values.push(cache.get(i));
+ values.push(cache.get(i)!);
assert.strictEqual(cache.get(i), i);
}
assert.deepStrictEqual(cache.values(), values);
@@ -194,7 +194,7 @@ suite('Map', () => {
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [7, 8, 9, 10, 11]);
let values: number[] = [];
- cache.keys().forEach(key => values.push(cache.get(key)));
+ cache.keys().forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [7, 8, 9, 10, 11]);
assert.deepStrictEqual(cache.values(), values);
});
@@ -588,7 +588,7 @@ suite('Map', () => {
test('mapToSerializable / serializableToMap', function () {
const map = new Map();
map.set('1', 'foo');
- map.set('2', null);
+ map.set('2', null!);
map.set('3', 'bar');
const map2 = serializableToMap(mapToSerializable(map));
diff --git a/src/vs/base/test/common/octicon.test.ts b/src/vs/base/test/common/octicon.test.ts
index 9135c38e1e2..c91055525d2 100644
--- a/src/vs/base/test/common/octicon.test.ts
+++ b/src/vs/base/test/common/octicon.test.ts
@@ -8,7 +8,7 @@ import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon'
export interface IOcticonFilter {
// Returns null if word doesn't match.
- (query: string, target: { text: string, octiconOffsets?: number[] }): IMatch[];
+ (query: string, target: { text: string, octiconOffsets?: number[] }): IMatch[] | null;
}
function filterOk(filter: IOcticonFilter, word: string, target: { text: string, octiconOffsets?: number[] }, highlights?: { start: number; end: number; }[]) {
diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts
index 2e8ee07797b..cee9c7a1b55 100644
--- a/src/vs/base/test/common/strings.test.ts
+++ b/src/vs/base/test/common/strings.test.ts
@@ -320,7 +320,7 @@ suite('Strings', () => {
});
test('fuzzyContains', () => {
- assert.ok(!strings.fuzzyContains(void 0, null));
+ assert.ok(!strings.fuzzyContains((void 0)!, null!));
assert.ok(strings.fuzzyContains('hello world', 'h'));
assert.ok(!strings.fuzzyContains('hello world', 'q'));
assert.ok(strings.fuzzyContains('hello world', 'hw'));
diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts
index 77351bee75e..44b26dfe7b1 100644
--- a/src/vs/base/test/common/uri.test.ts
+++ b/src/vs/base/test/common/uri.test.ts
@@ -91,9 +91,9 @@ suite('URI', () => {
test('with, identity', () => {
let uri = URI.parse('foo:bar/path');
- let uri2 = uri.with(null);
+ let uri2 = uri.with(null!);
assert.ok(uri === uri2);
- uri2 = uri.with(undefined);
+ uri2 = uri.with(undefined!);
assert.ok(uri === uri2);
uri2 = uri.with({});
assert.ok(uri === uri2);
diff --git a/src/vs/base/test/node/config.test.ts b/src/vs/base/test/node/config.test.ts
index ee4f4e38c74..59df2e0d36f 100644
--- a/src/vs/base/test/node/config.test.ts
+++ b/src/vs/base/test/node/config.test.ts
@@ -141,7 +141,7 @@ suite('Config', () => {
testFile('config', 'config.json').then(res => {
fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "bar" }');
- let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile, { changeBufferDelay: 100, onError: console.error, defaultConfig: void 0 });
+ let watcher = new ConfigWatcher<{ foo: string; }>(res.testFile, { changeBufferDelay: 100, onError: console.error, defaultConfig: { foo: 'bar' } });
watcher.getConfig(); // ensure we are in sync
fs.writeFileSync(res.testFile, '// my comment\n{ "foo": "changed" }');
diff --git a/src/vs/base/test/node/extfs/extfs.test.ts b/src/vs/base/test/node/extfs/extfs.test.ts
index 4031d3080da..b540aab4aae 100644
--- a/src/vs/base/test/node/extfs/extfs.test.ts
+++ b/src/vs/base/test/node/extfs/extfs.test.ts
@@ -38,7 +38,7 @@ function toReadable(value: string, throwError?: boolean): Readable {
this.emit('error', new Error(readError));
}
- let res: string;
+ let res!: string;
let canPush = true;
while (canPush && (res = stringChunks[counter++])) {
canPush = this.push(res);
@@ -96,14 +96,14 @@ suite('Extfs', () => {
return done(error);
}
- assert.ok(!statAndIsLink.isSymbolicLink);
+ assert.ok(!statAndIsLink!.isSymbolicLink);
extfs.statLink(symbolicLink, (error, statAndIsLink) => {
if (error) {
return done(error);
}
- assert.ok(statAndIsLink.isSymbolicLink);
+ assert.ok(statAndIsLink!.isSymbolicLink);
extfs.delSync(directory);
done();
});
@@ -258,7 +258,7 @@ suite('Extfs', () => {
assert.ok(fs.existsSync(newDir));
- extfs.writeFileAndFlush(testFile, 'Hello World', null, error => {
+ extfs.writeFileAndFlush(testFile, 'Hello World', null!, error => {
if (error) {
return done(error);
}
@@ -267,7 +267,7 @@ suite('Extfs', () => {
const largeString = (new Array(100 * 1024)).join('Large String\n');
- extfs.writeFileAndFlush(testFile, largeString, null, error => {
+ extfs.writeFileAndFlush(testFile, largeString, null!, error => {
if (error) {
return done(error);
}
@@ -293,7 +293,7 @@ suite('Extfs', () => {
assert.ok(fs.existsSync(newDir));
- extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => {
+ extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null!, error => {
if (error) {
return done(error);
}
@@ -302,7 +302,7 @@ suite('Extfs', () => {
const largeString = (new Array(100 * 1024)).join('Large String\n');
- extfs.writeFileAndFlush(testFile, toReadable(largeString), null, error => {
+ extfs.writeFileAndFlush(testFile, toReadable(largeString), null!, error => {
if (error) {
return done(error);
}
@@ -329,7 +329,7 @@ suite('Extfs', () => {
assert.ok(fs.existsSync(newDir));
- extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => {
+ extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => {
if (error) {
return done(error);
}
@@ -356,7 +356,7 @@ suite('Extfs', () => {
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
- extfs.writeFileAndFlush(testFile, 'Hello World', null, error => {
+ extfs.writeFileAndFlush(testFile, 'Hello World', null!, error => {
if (!error) {
return done(new Error('Expected error for writing to readonly file'));
}
@@ -382,7 +382,7 @@ suite('Extfs', () => {
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
const readable = toReadable('Hello World');
- extfs.writeFileAndFlush(testFile, readable, null, error => {
+ extfs.writeFileAndFlush(testFile, readable, null!, error => {
if (!error || (error).code !== 'EISDIR') {
return done(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (error).code : 'no error')));
}
@@ -408,7 +408,7 @@ suite('Extfs', () => {
assert.ok(fs.existsSync(newDir));
- extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null, error => {
+ extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null!, error => {
if (!error || error.message !== readError) {
return done(new Error('Expected error for writing to folder'));
}
@@ -438,7 +438,7 @@ suite('Extfs', () => {
fs.writeFileSync(testFile, '');
fs.chmodSync(testFile, 33060); // make readonly
- extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => {
+ extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null!, error => {
if (!error || !((error).code !== 'EACCES' || (error).code !== 'EPERM')) {
return done(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (error).code : 'no error')));
}
@@ -464,7 +464,7 @@ suite('Extfs', () => {
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
- extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => {
+ extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => {
if (!error) {
return done(new Error('Expected error for writing to folder'));
}
@@ -487,12 +487,12 @@ suite('Extfs', () => {
assert.ok(fs.existsSync(newDir));
- extfs.writeFileAndFlushSync(testFile, 'Hello World', null);
+ extfs.writeFileAndFlushSync(testFile, 'Hello World', null!);
assert.equal(fs.readFileSync(testFile), 'Hello World');
const largeString = (new Array(100 * 1024)).join('Large String\n');
- extfs.writeFileAndFlushSync(testFile, largeString, null);
+ extfs.writeFileAndFlushSync(testFile, largeString, null!);
assert.equal(fs.readFileSync(testFile), largeString);
extfs.del(parentDir, os.tmpdir(), done, ignore);
@@ -550,7 +550,7 @@ suite('Extfs', () => {
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
- let realpath: string;
+ let realpath!: string;
try {
realpath = extfs.realpathSync(newDir);
} catch (error) {
diff --git a/src/vs/base/test/node/glob.test.ts b/src/vs/base/test/node/glob.test.ts
index 4f851a4ca4f..7b003cc002b 100644
--- a/src/vs/base/test/node/glob.test.ts
+++ b/src/vs/base/test/node/glob.test.ts
@@ -738,24 +738,24 @@ suite('Glob', () => {
});
test('falsy expression/pattern', function () {
- assert.strictEqual(glob.match(null, 'foo'), false);
+ assert.strictEqual(glob.match(null!, 'foo'), false);
assert.strictEqual(glob.match('', 'foo'), false);
- assert.strictEqual(glob.parse(null)('foo'), false);
+ assert.strictEqual(glob.parse(null!)('foo'), false);
assert.strictEqual(glob.parse('')('foo'), false);
});
test('falsy path', function () {
- assert.strictEqual(glob.parse('foo')(null), false);
+ assert.strictEqual(glob.parse('foo')(null!), false);
assert.strictEqual(glob.parse('foo')(''), false);
- assert.strictEqual(glob.parse('**/*.j?')(null), false);
+ assert.strictEqual(glob.parse('**/*.j?')(null!), false);
assert.strictEqual(glob.parse('**/*.j?')(''), false);
- assert.strictEqual(glob.parse('**/*.foo')(null), false);
+ assert.strictEqual(glob.parse('**/*.foo')(null!), false);
assert.strictEqual(glob.parse('**/*.foo')(''), false);
- assert.strictEqual(glob.parse('**/foo')(null), false);
+ assert.strictEqual(glob.parse('**/foo')(null!), false);
assert.strictEqual(glob.parse('**/foo')(''), false);
- assert.strictEqual(glob.parse('{**/baz,**/foo}')(null), false);
+ assert.strictEqual(glob.parse('{**/baz,**/foo}')(null!), false);
assert.strictEqual(glob.parse('{**/baz,**/foo}')(''), false);
- assert.strictEqual(glob.parse('{**/*.baz,**/*.foo}')(null), false);
+ assert.strictEqual(glob.parse('{**/*.baz,**/*.foo}')(null!), false);
assert.strictEqual(glob.parse('{**/*.baz,**/*.foo}')(''), false);
});
@@ -808,7 +808,7 @@ suite('Glob', () => {
}, ['foo', 'bar', 'baz'], [
['bar/foo', '**/foo/**'],
['foo/bar', '{**/bar/**,**/baz/**}'],
- ['bar/nope', null]
+ ['bar/nope', null!]
]);
const siblings = ['baz', 'baz.zip', 'nope'];
@@ -817,12 +817,12 @@ suite('Glob', () => {
'**/foo/**': { when: '$(basename).zip' },
'**/bar/**': true
}, ['bar'], [
- ['bar/foo', null],
- ['bar/foo/baz', null],
- ['bar/foo/nope', null],
+ ['bar/foo', null!],
+ ['bar/foo/baz', null!],
+ ['bar/foo/nope', null!],
['foo/bar', '**/bar/**'],
], [
- null,
+ null!,
hasSibling,
hasSibling
]);
@@ -832,7 +832,7 @@ suite('Glob', () => {
const parsed = glob.parse(pattern, { trimForExclusions: true });
assert.deepStrictEqual(glob.getBasenameTerms(parsed), basenameTerms);
matches.forEach(([text, result], i) => {
- assert.strictEqual(parsed(text, null, siblingsFns[i]), result);
+ assert.strictEqual(parsed(text, null!, siblingsFns[i]), result);
});
}
@@ -914,7 +914,7 @@ suite('Glob', () => {
[nativeSep('bar/foo/bar'), '**/foo/bar/**'],
// Not supported
// [nativeSep('foo/bar/bar'), '{**/bar/bar/**,**/baz/bar/**}'],
- [nativeSep('/foo/bar/nope'), null]
+ [nativeSep('/foo/bar/nope'), null!]
]);
const siblings = ['baz', 'baz.zip', 'nope'];
@@ -923,12 +923,12 @@ suite('Glob', () => {
'**/foo/123/**': { when: '$(basename).zip' },
'**/bar/123/**': true
}, ['*/bar/123'], [
- [nativeSep('bar/foo/123'), null],
- [nativeSep('bar/foo/123/baz'), null],
- [nativeSep('bar/foo/123/nope'), null],
+ [nativeSep('bar/foo/123'), null!],
+ [nativeSep('bar/foo/123/baz'), null!],
+ [nativeSep('bar/foo/123/nope'), null!],
[nativeSep('foo/bar/123'), '**/bar/123/**'],
], [
- null,
+ null!,
hasSibling,
hasSibling
]);
@@ -938,7 +938,7 @@ suite('Glob', () => {
const parsed = glob.parse(pattern, { trimForExclusions: true });
assert.deepStrictEqual(glob.getPathTerms(parsed), pathTerms);
matches.forEach(([text, result], i) => {
- assert.strictEqual(parsed(text, null, siblingsFns[i]), result);
+ assert.strictEqual(parsed(text, null!, siblingsFns[i]), result);
});
}
diff --git a/src/vs/base/test/node/pfs.test.ts b/src/vs/base/test/node/pfs.test.ts
index 6edeabd4d58..172ef642d5d 100644
--- a/src/vs/base/test/node/pfs.test.ts
+++ b/src/vs/base/test/node/pfs.test.ts
@@ -24,7 +24,7 @@ suite('PFS', () => {
return pfs.mkdirp(newDir, 493).then(() => {
assert.ok(fs.existsSync(newDir));
- return pfs.writeFile(testFile, 'Hello World', null).then(() => {
+ return pfs.writeFile(testFile, 'Hello World', null!).then(() => {
assert.equal(fs.readFileSync(testFile), 'Hello World');
return pfs.del(parentDir, os.tmpdir());
@@ -46,11 +46,11 @@ suite('PFS', () => {
assert.ok(fs.existsSync(newDir));
return Promise.all([
- pfs.writeFile(testFile1, 'Hello World 1', null),
- pfs.writeFile(testFile2, 'Hello World 2', null),
- pfs.writeFile(testFile3, 'Hello World 3', null),
- pfs.writeFile(testFile4, 'Hello World 4', null),
- pfs.writeFile(testFile5, 'Hello World 5', null)
+ pfs.writeFile(testFile1, 'Hello World 1', null!),
+ pfs.writeFile(testFile2, 'Hello World 2', null!),
+ pfs.writeFile(testFile3, 'Hello World 3', null!),
+ pfs.writeFile(testFile4, 'Hello World 4', null!),
+ pfs.writeFile(testFile5, 'Hello World 5', null!)
]).then(() => {
assert.equal(fs.readFileSync(testFile1), 'Hello World 1');
assert.equal(fs.readFileSync(testFile2), 'Hello World 2');
diff --git a/src/vs/base/test/node/storage/storage.test.ts b/src/vs/base/test/node/storage/storage.test.ts
index 0acbb97461c..134379de4ab 100644
--- a/src/vs/base/test/node/storage/storage.test.ts
+++ b/src/vs/base/test/node/storage/storage.test.ts
@@ -99,7 +99,7 @@ suite('Storage Library', () => {
await mkdirp(storageDir);
class TestSQLiteStorageDatabase extends SQLiteStorageDatabase {
- private _onDidChangeItemsExternal: Emitter = new Emitter();
+ private _onDidChangeItemsExternal = new Emitter();
get onDidChangeItemsExternal(): Event { return this._onDidChangeItemsExternal.event; }
fireDidChangeItemsExternal(event: IStorageItemsChangeEvent): void {
diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts b/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts
index 6784a68ebd9..03f038fc1fb 100644
--- a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts
+++ b/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts
@@ -8,11 +8,13 @@ import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedPr
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner';
+import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
export function createSharedProcessContributions(service: IInstantiationService): IDisposable {
return combinedDisposable([
service.createInstance(NodeCachedDataCleaner),
service.createInstance(LanguagePackCachedDataCleaner),
- service.createInstance(StorageDataCleaner)
+ service.createInstance(StorageDataCleaner),
+ service.createInstance(LogsDataCleaner)
]);
}
diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner.ts
new file mode 100644
index 00000000000..2cf74b7bfa0
--- /dev/null
+++ b/src/vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner.ts
@@ -0,0 +1,40 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { IEnvironmentService } from 'vs/platform/environment/common/environment';
+import { join, dirname, basename } from 'path';
+import { readdir, rimraf } from 'vs/base/node/pfs';
+import { onUnexpectedError } from 'vs/base/common/errors';
+import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
+
+export class LogsDataCleaner extends Disposable {
+
+ constructor(
+ @IEnvironmentService private environmentService: IEnvironmentService
+ ) {
+ super();
+
+ this.cleanUpOldLogsSoon();
+ }
+
+ private cleanUpOldLogsSoon(): void {
+ let handle: any = setTimeout(() => {
+ handle = void 0;
+
+ const currentLog = basename(this.environmentService.logsPath);
+ const logsRoot = dirname(this.environmentService.logsPath);
+
+ readdir(logsRoot).then(children => {
+ const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name));
+ const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog);
+ const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
+
+ return Promise.all(toDelete.map(name => rimraf(join(logsRoot, name))));
+ }).then(null, onUnexpectedError);
+ }, 10 * 1000);
+
+ this._register(toDisposable(() => clearTimeout(handle)));
+ }
+}
diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts
index b25ad242115..205c1ee3e67 100644
--- a/src/vs/code/electron-main/app.ts
+++ b/src/vs/code/electron-main/app.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol } from 'electron';
-import * as platform from 'vs/base/common/platform';
+import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
import { WindowsManager } from 'vs/code/electron-main/windows';
import { IWindowsService, OpenContext, ActiveWindowManager } from 'vs/platform/windows/common/windows';
import { WindowsChannel } from 'vs/platform/windows/node/windowsIpc';
@@ -63,7 +63,7 @@ import { MenubarChannel } from 'vs/platform/menubar/node/menubarIpc';
import { hasArgs } from 'vs/platform/environment/node/argv';
import { RunOnceScheduler } from 'vs/base/common/async';
import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu';
-import { THEME_STORAGE_KEY, THEME_BG_STORAGE_KEY } from 'vs/code/electron-main/theme';
+import { storeBackgroundColor } from 'vs/code/electron-main/theme';
import { nativeSep, join } from 'vs/base/common/paths';
import { homedir } from 'os';
import { localize } from 'vs/nls';
@@ -74,6 +74,12 @@ import { SnapUpdateService } from 'vs/platform/update/electron-main/updateServic
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/node/storageMainService';
import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIpc';
import { generateUuid } from 'vs/base/common/uuid';
+import { startsWith } from 'vs/base/common/strings';
+import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
+import { IBackupMainService } from 'vs/platform/backup/common/backup';
+import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService';
+import { URLService } from 'vs/platform/url/common/urlService';
+import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
export class CodeApplication extends Disposable {
@@ -88,14 +94,13 @@ export class CodeApplication extends Disposable {
constructor(
private mainIpcServer: Server,
- private userEnv: platform.IProcessEnvironment,
+ private userEnv: IProcessEnvironment,
@IInstantiationService private instantiationService: IInstantiationService,
@ILogService private logService: ILogService,
@IEnvironmentService private environmentService: IEnvironmentService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IConfigurationService private configurationService: ConfigurationService,
- @IStateService private stateService: IStateService,
- @IHistoryMainService private historyMainService: IHistoryMainService,
+ @IStateService private stateService: IStateService
) {
super();
@@ -138,12 +143,27 @@ export class CodeApplication extends Disposable {
app.on('web-contents-created', (event: any, contents) => {
contents.on('will-attach-webview', (event: Electron.Event, webPreferences, params) => {
+ const isValidWebviewSource = (source: string): boolean => {
+ if (!source) {
+ return false;
+ }
+
+ if (source === 'data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E') {
+ return true;
+ }
+
+ const srcUri = URI.parse(source).fsPath.toLowerCase();
+ const rootUri = URI.file(this.environmentService.appRoot).fsPath.toLowerCase();
+
+ return startsWith(srcUri, rootUri + nativeSep);
+ };
+
// Ensure defaults
delete webPreferences.preload;
webPreferences.nodeIntegration = false;
// Verify URLs being loaded
- if (this.isValidWebviewSource(params.src) && this.isValidWebviewSource(webPreferences.preloadURL)) {
+ if (isValidWebviewSource(params.src) && isValidWebviewSource(webPreferences.preloadURL)) {
return;
}
@@ -168,85 +188,6 @@ export class CodeApplication extends Disposable {
});
});
- const connectionPool: Map = new Map();
-
- class ActiveConnection {
- private _authority: string;
- private _client: Promise>;
- private _disposeRunner: RunOnceScheduler;
-
- constructor(authority: string, host: string, port: number) {
- this._authority = authority;
- this._client = connectRemoteAgentManagement(authority, host, port, `main`);
- this._disposeRunner = new RunOnceScheduler(() => this._dispose(), 5000);
- }
-
- private _dispose(): void {
- this._disposeRunner.dispose();
- connectionPool.delete(this._authority);
- this._client.then((connection) => {
- connection.dispose();
- });
- }
-
- public getClient(): Promise> {
- this._disposeRunner.schedule();
- return this._client;
- }
- }
-
- const resolvedAuthorities = new Map();
- ipc.on('vscode:remoteAuthorityResolved', (event: any, data: ResolvedAuthority) => {
- resolvedAuthorities.set(data.authority, data);
- });
- const resolveAuthority = (authority: string): ResolvedAuthority | null => {
- if (authority.indexOf('+') >= 0) {
- if (resolvedAuthorities.has(authority)) {
- return resolvedAuthorities.get(authority);
- }
- return null;
- } else {
- const [host, strPort] = authority.split(':');
- const port = parseInt(strPort, 10);
- return { authority, host, port, syncExtensions: false };
- }
- };
-
- protocol.registerBufferProtocol(REMOTE_HOST_SCHEME, async (request, callback) => {
- if (request.method !== 'GET') {
- return callback(null);
- }
- const uri = URI.parse(request.url);
-
- let activeConnection: ActiveConnection = null;
- if (connectionPool.has(uri.authority)) {
- activeConnection = connectionPool.get(uri.authority);
- } else {
- let resolvedAuthority = resolveAuthority(uri.authority);
- if (!resolvedAuthority) {
- callback(null);
- return;
- }
- activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port);
- connectionPool.set(uri.authority, activeConnection);
- }
- try {
- const rawClient = await activeConnection.getClient();
- if (connectionPool.has(uri.authority)) { // not disposed in the meantime
- const channel = rawClient.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
-
- // TODO@alex don't use call directly, wrap it around a `RemoteExtensionsFileSystemProvider`
- const fileContents = await channel.call('readFile', [uri]);
- callback(Buffer.from(fileContents));
- } else {
- callback(null);
- }
- } catch (err) {
- errors.onUnexpectedError(err);
- callback(null);
- }
- });
-
let macOpenFileURIs: URI[] = [];
let runningTimeout: any = null;
app.on('open-file', (event: Event, path: string) => {
@@ -315,38 +256,10 @@ export class CodeApplication extends Disposable {
}
});
- ipc.on('vscode:toggleDevTools', (event: Event) => {
- event.sender.toggleDevTools();
- });
+ ipc.on('vscode:toggleDevTools', (event: Event) => event.sender.toggleDevTools());
+ ipc.on('vscode:openDevTools', (event: Event) => event.sender.openDevTools());
- ipc.on('vscode:openDevTools', (event: Event) => {
- event.sender.openDevTools();
- });
-
- ipc.on('vscode:reloadWindow', (event: Event) => {
- event.sender.reload();
- });
-
- // Keyboard layout changes
- KeyboardLayoutMonitor.INSTANCE.onDidChangeKeyboardLayout(() => {
- if (this.windowsMainService) {
- this.windowsMainService.sendToAll('vscode:keyboardLayoutChanged', false);
- }
- });
- }
-
- private isValidWebviewSource(source: string): boolean {
- if (!source) {
- return false;
- }
-
- if (source === 'data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E') {
- return true;
- }
-
- const srcUri: any = URI.parse(source).fsPath.toLowerCase();
- const rootUri = URI.file(this.environmentService.appRoot).fsPath.toLowerCase();
- return srcUri.startsWith(rootUri + nativeSep);
+ ipc.on('vscode:reloadWindow', (event: Event) => event.sender.reload());
}
private onUnexpectedError(err: Error): void {
@@ -374,10 +287,7 @@ export class CodeApplication extends Disposable {
// Theme changes
if (event === 'vscode:changeColorTheme' && typeof payload === 'string') {
- let data = JSON.parse(payload);
-
- this.stateService.setItem(THEME_STORAGE_KEY, data.baseTheme);
- this.stateService.setItem(THEME_BG_STORAGE_KEY, data.background);
+ storeBackgroundColor(this.stateService, JSON.parse(payload));
}
}
@@ -390,7 +300,7 @@ export class CodeApplication extends Disposable {
// This will help Windows to associate the running program with
// any shortcut that is pinned to the taskbar and prevent showing
// two icons in the taskbar for the same app.
- if (platform.isWindows && product.win32AppUserModelId) {
+ if (isWindows && product.win32AppUserModelId) {
app.setAppUserModelId(product.win32AppUserModelId);
}
@@ -401,7 +311,7 @@ export class CodeApplication extends Disposable {
// Explicitly opt out of the patch here before creating any windows.
// See: https://github.com/Microsoft/vscode/issues/35361#issuecomment-399794085
try {
- if (platform.isMacintosh && this.configurationService.getValue('window.nativeTabs') === true && !systemPreferences.getUserDefault('NSUseImprovedLayoutPass', 'boolean')) {
+ if (isMacintosh && this.configurationService.getValue('window.nativeTabs') === true && !systemPreferences.getUserDefault('NSUseImprovedLayoutPass', 'boolean')) {
systemPreferences.setUserDefault('NSUseImprovedLayoutPass', 'boolean', true as any);
}
} catch (error) {
@@ -511,7 +421,7 @@ export class CodeApplication extends Disposable {
services.set(IUpdateService, new SyncDescriptor(Win32UpdateService));
} else if (process.platform === 'linux') {
if (process.env.SNAP && process.env.SNAP_REVISION) {
- services.set(IUpdateService, new SyncDescriptor(SnapUpdateService));
+ services.set(IUpdateService, new SyncDescriptor(SnapUpdateService, [process.env.SNAP, process.env.SNAP_REVISION]));
} else {
services.set(IUpdateService, new SyncDescriptor(LinuxUpdateService));
}
@@ -525,6 +435,10 @@ export class CodeApplication extends Disposable {
services.set(IIssueService, new SyncDescriptor(IssueService, [machineId, this.userEnv]));
services.set(IMenubarService, new SyncDescriptor(MenubarService));
services.set(IStorageMainService, new SyncDescriptor(StorageMainService));
+ services.set(IBackupMainService, new SyncDescriptor(BackupMainService));
+ services.set(IHistoryMainService, new SyncDescriptor(HistoryMainService));
+ services.set(IURLService, new SyncDescriptor(URLService));
+ services.set(IWorkspacesMainService, new SyncDescriptor(WorkspacesMainService));
// Telemetry
if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
@@ -630,8 +544,6 @@ export class CodeApplication extends Disposable {
// Propagate to clients
const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); // TODO@Joao: unfold this
- const args = this.environmentService.args;
-
// Create a URL handler which forwards to the last active window
const activeWindowManager = new ActiveWindowManager(windowsService);
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
@@ -640,7 +552,7 @@ export class CodeApplication extends Disposable {
// On Mac, Code can be running without any open windows, so we must create a window to handle urls,
// if there is none
- if (platform.isMacintosh) {
+ if (isMacintosh) {
const environmentService = accessor.get(IEnvironmentService);
urlService.registerHandler({
@@ -661,6 +573,7 @@ export class CodeApplication extends Disposable {
urlService.registerHandler(multiplexURLHandler);
// Watch Electron URLs and forward them to the UrlService
+ const args = this.environmentService.args;
const urls = args['open-url'] ? args._urls : [];
const urlListener = new ElectronURLListener(urls, urlService, this.windowsMainService);
this._register(urlListener);
@@ -687,9 +600,10 @@ export class CodeApplication extends Disposable {
private afterWindowOpen(accessor: ServicesAccessor): void {
const windowsMainService = accessor.get(IWindowsMainService);
+ const historyMainService = accessor.get(IHistoryMainService);
let windowsMutex: Mutex | null = null;
- if (platform.isWindows) {
+ if (isWindows) {
// Setup Windows mutex
try {
@@ -711,7 +625,7 @@ export class CodeApplication extends Disposable {
// Ensure Windows foreground love module
try {
// tslint:disable-next-line:no-unused-expression
- require.__$__nodeRequire('windows-foreground-love');
+ require.__$__nodeRequire('windows-foreground-love');
} catch (e) {
if (!this.environmentService.isBuilt) {
windowsMainService.showMessageBox({
@@ -725,12 +639,105 @@ export class CodeApplication extends Disposable {
}
}
+ // Remote Authorities
+ this.handleRemoteAuthorities();
+
+ // Keyboard layout changes
+ KeyboardLayoutMonitor.INSTANCE.onDidChangeKeyboardLayout(() => {
+ this.windowsMainService.sendToAll('vscode:keyboardLayoutChanged', false);
+ });
+
// Jump List
- this.historyMainService.updateWindowsJumpList();
- this.historyMainService.onRecentlyOpenedChange(() => this.historyMainService.updateWindowsJumpList());
+ historyMainService.updateWindowsJumpList();
+ historyMainService.onRecentlyOpenedChange(() => historyMainService.updateWindowsJumpList());
// Start shared process after a while
const sharedProcessSpawn = this._register(new RunOnceScheduler(() => getShellEnvironment().then(userEnv => this.sharedProcess.spawn(userEnv)), 3000));
sharedProcessSpawn.schedule();
}
+
+ private handleRemoteAuthorities(): void {
+ const connectionPool: Map = new Map();
+
+ const isBuilt = this.environmentService.isBuilt;
+
+ class ActiveConnection {
+ private _authority: string;
+ private _client: Promise>;
+ private _disposeRunner: RunOnceScheduler;
+
+ constructor(authority: string, host: string, port: number) {
+ this._authority = authority;
+ this._client = connectRemoteAgentManagement(authority, host, port, `main`, isBuilt);
+ this._disposeRunner = new RunOnceScheduler(() => this._dispose(), 5000);
+ }
+
+ private _dispose(): void {
+ this._disposeRunner.dispose();
+ connectionPool.delete(this._authority);
+ this._client.then((connection) => {
+ connection.dispose();
+ });
+ }
+
+ public getClient(): Promise> {
+ this._disposeRunner.schedule();
+ return this._client;
+ }
+ }
+
+ const resolvedAuthorities = new Map();
+ ipc.on('vscode:remoteAuthorityResolved', (event: any, data: ResolvedAuthority) => {
+ resolvedAuthorities.set(data.authority, data);
+ });
+
+ const resolveAuthority = (authority: string): ResolvedAuthority | null => {
+ if (authority.indexOf('+') >= 0) {
+ if (resolvedAuthorities.has(authority)) {
+ return resolvedAuthorities.get(authority);
+ }
+ return null;
+ } else {
+ const [host, strPort] = authority.split(':');
+ const port = parseInt(strPort, 10);
+ return { authority, host, port, syncExtensions: false };
+ }
+ };
+
+ protocol.registerBufferProtocol(REMOTE_HOST_SCHEME, async (request, callback) => {
+ if (request.method !== 'GET') {
+ return callback(null);
+ }
+ const uri = URI.parse(request.url);
+
+ let activeConnection: ActiveConnection = null;
+ if (connectionPool.has(uri.authority)) {
+ activeConnection = connectionPool.get(uri.authority);
+ } else {
+ let resolvedAuthority = resolveAuthority(uri.authority);
+ if (!resolvedAuthority) {
+ callback(null);
+ return;
+ }
+ activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port);
+ connectionPool.set(uri.authority, activeConnection);
+ }
+ try {
+ const rawClient = await activeConnection.getClient();
+ if (connectionPool.has(uri.authority)) { // not disposed in the meantime
+ const channel = rawClient.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
+
+ // TODO@alex don't use call directly, wrap it around a `RemoteExtensionsFileSystemProvider`
+ const fileContents = await channel.call('readFile', [uri]);
+ callback(Buffer.from(fileContents));
+ } else {
+ callback(null);
+ }
+ } catch (err) {
+ errors.onUnexpectedError(err);
+ callback(null);
+ }
+ });
+ }
}
+
diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts
index b3f48067b9a..2165dcc944f 100644
--- a/src/vs/code/electron-main/main.ts
+++ b/src/vs/code/electron-main/main.ts
@@ -8,9 +8,8 @@ import { app, dialog } from 'electron';
import { assign } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
-import * as path from 'path';
import { parseMainProcessArgv } from 'vs/platform/environment/node/argv';
-import { mkdirp, readdir, rimraf } from 'vs/base/node/pfs';
+import { mkdirp } from 'vs/base/node/pfs';
import { validatePaths } from 'vs/code/node/paths';
import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
@@ -22,22 +21,14 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ILogService, ConsoleLogMainService, MultiplexLogService, getLogLevel } from 'vs/platform/log/common/log';
import { StateService } from 'vs/platform/state/node/stateService';
import { IStateService } from 'vs/platform/state/common/state';
-import { IBackupMainService } from 'vs/platform/backup/common/backup';
-import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
import { IRequestService } from 'vs/platform/request/node/request';
import { RequestService } from 'vs/platform/request/electron-main/requestService';
-import { IURLService } from 'vs/platform/url/common/url';
-import { URLService } from 'vs/platform/url/common/urlService';
import * as fs from 'fs';
import { CodeApplication } from 'vs/code/electron-main/app';
-import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService';
-import { IHistoryMainService } from 'vs/platform/history/common/history';
-import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
-import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { localize } from 'vs/nls';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
@@ -45,67 +36,16 @@ import { IDiagnosticsService, DiagnosticsService } from 'vs/platform/diagnostics
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
import { uploadLogs } from 'vs/code/electron-main/logUploader';
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
-import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
-import { CommandLineDialogService } from 'vs/platform/dialogs/node/dialogService';
import { createWaitMarkerFile } from 'vs/code/node/wait';
-function createServices(args: ParsedArgs, bufferLogService: BufferLogService): IInstantiationService {
- const services = new ServiceCollection();
-
- const environmentService = new EnvironmentService(args, process.execPath);
-
- const logService = new MultiplexLogService([new ConsoleLogMainService(getLogLevel(environmentService)), bufferLogService]);
- process.once('exit', () => logService.dispose());
- setTimeout(() => cleanupOlderLogs(environmentService).then(null, err => console.error(err)), 10000);
-
- services.set(IEnvironmentService, environmentService);
- services.set(ILogService, logService);
- services.set(IWorkspacesMainService, new SyncDescriptor(WorkspacesMainService));
- services.set(IHistoryMainService, new SyncDescriptor(HistoryMainService));
- services.set(ILifecycleService, new SyncDescriptor(LifecycleService));
- services.set(IStateService, new SyncDescriptor(StateService));
- services.set(IConfigurationService, new SyncDescriptor(ConfigurationService));
- services.set(IRequestService, new SyncDescriptor(RequestService));
- services.set(IURLService, new SyncDescriptor(URLService));
- services.set(IBackupMainService, new SyncDescriptor(BackupMainService));
- services.set(IDialogService, new SyncDescriptor(CommandLineDialogService));
- services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
-
- return new InstantiationService(services, true);
-}
-
-/**
- * Cleans up older logs, while keeping the 10 most recent ones.
-*/
-async function cleanupOlderLogs(environmentService: EnvironmentService): Promise {
- const currentLog = path.basename(environmentService.logsPath);
- const logsRoot = path.dirname(environmentService.logsPath);
- const children = await readdir(logsRoot);
- const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name));
- const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog);
- const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
-
- await Promise.all(toDelete.map(name => rimraf(path.join(logsRoot, name))));
-}
-
-function createPaths(environmentService: IEnvironmentService): Promise {
- const paths = [
- environmentService.extensionsPath,
- environmentService.nodeCachedDataDir,
- environmentService.logsPath,
- environmentService.globalStorageHome,
- environmentService.workspaceStorageHome
- ];
-
- return Promise.all(paths.map(path => path && mkdirp(path)));
-}
-
class ExpectedError extends Error {
- public readonly isExpected = true;
+ readonly isExpected = true;
}
function setupIPC(accessor: ServicesAccessor): Promise {
const logService = accessor.get(ILogService);
+ const environmentService = accessor.get(IEnvironmentService);
+ const instantiationService = accessor.get(IInstantiationService);
function allowSetForegroundWindow(service: LaunchChannelClient): Promise {
let promise: Promise = Promise.resolve();
@@ -127,8 +67,6 @@ function setupIPC(accessor: ServicesAccessor): Promise {
}
function setup(retry: boolean): Promise {
- const environmentService = accessor.get(IEnvironmentService);
-
return serve(environmentService.mainIPCHandle).then(server => {
// Print --status usage info
@@ -154,7 +92,15 @@ function setupIPC(accessor: ServicesAccessor): Promise {
return server;
}, err => {
+
+ // Handle unexpected errors (the only expected error is EADDRINUSE that
+ // indicates a second instance of Code is running)
if (err.code !== 'EADDRINUSE') {
+
+ // Show a dialog for errors that can be resolved by the user
+ handleStartupDataDirError(environmentService, err);
+
+ // Any other runtime error is just printed to the console
return Promise.reject(err);
}
@@ -195,14 +141,18 @@ function setupIPC(accessor: ServicesAccessor): Promise {
// Process Info
if (environmentService.args.status) {
return service.getMainProcessInfo().then(info => {
- return accessor.get(IDiagnosticsService).printDiagnostics(info).then(() => Promise.reject(new ExpectedError()));
+ return instantiationService.invokeFunction(accessor => {
+ return accessor.get(IDiagnosticsService).printDiagnostics(info).then(() => Promise.reject(new ExpectedError()));
+ });
});
}
// Log uploader
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
- return uploadLogs(service, accessor.get(IRequestService), environmentService)
- .then(() => Promise.reject(new ExpectedError()));
+ return instantiationService.invokeFunction(accessor => {
+ return uploadLogs(service, accessor.get(IRequestService), environmentService)
+ .then(() => Promise.reject(new ExpectedError()));
+ });
}
logService.trace('Sending env to running instance...');
@@ -262,6 +212,15 @@ function showStartupWarningDialog(message: string, detail: string): void {
});
}
+function handleStartupDataDirError(environmentService: IEnvironmentService, error): void {
+ if (error.code === 'EACCES' || error.code === 'EPERM') {
+ showStartupWarningDialog(
+ localize('startupDataDirError', "Unable to write program user data."),
+ localize('startupDataDirErrorDetail', "Please make sure the directory {0} is writeable.", environmentService.userDataPath)
+ );
+ }
+}
+
function quit(accessor: ServicesAccessor, reason?: ExpectedError | Error): void {
const logService = accessor.get(ILogService);
const lifecycleService = accessor.get(ILifecycleService);
@@ -313,14 +272,20 @@ function startup(args: ParsedArgs): void {
const instantiationService = createServices(args, bufferLogService);
instantiationService.invokeFunction(accessor => {
const environmentService = accessor.get(IEnvironmentService);
+ const stateService = accessor.get(IStateService);
// Patch `process.env` with the instance's environment
const instanceEnvironment = patchEnvironment(environmentService);
// Startup
- return instantiationService
- .invokeFunction(a => createPaths(a.get(IEnvironmentService)))
- .then(() => instantiationService.invokeFunction(setupIPC))
+ return initServices(environmentService, stateService as StateService)
+ .then(() => instantiationService.invokeFunction(setupIPC), error => {
+
+ // Show a dialog for errors that can be resolved by the user
+ handleStartupDataDirError(environmentService, error);
+
+ return Promise.reject(error);
+ })
.then(mainIpcServer => {
bufferLogService.logger = createSpdLogService('main', bufferLogService.getLevel(), environmentService.logsPath);
@@ -329,6 +294,43 @@ function startup(args: ParsedArgs): void {
}).then(null, err => instantiationService.invokeFunction(quit, err));
}
+function createServices(args: ParsedArgs, bufferLogService: BufferLogService): IInstantiationService {
+ const services = new ServiceCollection();
+
+ const environmentService = new EnvironmentService(args, process.execPath);
+
+ const logService = new MultiplexLogService([new ConsoleLogMainService(getLogLevel(environmentService)), bufferLogService]);
+ process.once('exit', () => logService.dispose());
+
+ services.set(IEnvironmentService, environmentService);
+ services.set(ILogService, logService);
+ services.set(ILifecycleService, new SyncDescriptor(LifecycleService));
+ services.set(IStateService, new SyncDescriptor(StateService));
+ services.set(IConfigurationService, new SyncDescriptor(ConfigurationService));
+ services.set(IRequestService, new SyncDescriptor(RequestService));
+ services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
+
+ return new InstantiationService(services, true);
+}
+
+function initServices(environmentService: IEnvironmentService, stateService: StateService): Promise {
+
+ // Ensure paths for environment service exist
+ const environmentServiceInitialization = Promise.all([
+ environmentService.extensionsPath,
+ environmentService.nodeCachedDataDir,
+ environmentService.logsPath,
+ environmentService.globalStorageHome,
+ environmentService.workspaceStorageHome,
+ environmentService.backupHome
+ ].map(path => path && mkdirp(path)));
+
+ // State service
+ const stateServiceInitialization = stateService.init();
+
+ return Promise.all([environmentServiceInitialization, stateServiceInitialization]);
+}
+
function main(): void {
// Set the error handler early enough so that we are not getting the
diff --git a/src/vs/code/electron-main/theme.ts b/src/vs/code/electron-main/theme.ts
index cd0f4bf02f4..5518c38404a 100644
--- a/src/vs/code/electron-main/theme.ts
+++ b/src/vs/code/electron-main/theme.ts
@@ -7,12 +7,17 @@ import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { systemPreferences } from 'electron';
import { IStateService } from 'vs/platform/state/common/state';
-export const DEFAULT_BG_LIGHT = '#FFFFFF';
-export const DEFAULT_BG_DARK = '#1E1E1E';
-export const DEFAULT_BG_HC_BLACK = '#000000';
+const DEFAULT_BG_LIGHT = '#FFFFFF';
+const DEFAULT_BG_DARK = '#1E1E1E';
+const DEFAULT_BG_HC_BLACK = '#000000';
-export const THEME_STORAGE_KEY = 'theme';
-export const THEME_BG_STORAGE_KEY = 'themeBackground';
+const THEME_STORAGE_KEY = 'theme';
+const THEME_BG_STORAGE_KEY = 'themeBackground';
+
+export function storeBackgroundColor(stateService: IStateService, data: { baseTheme: string, background: string }): void {
+ stateService.setItem(THEME_STORAGE_KEY, data.baseTheme);
+ stateService.setItem(THEME_BG_STORAGE_KEY, data.background);
+}
export function getBackgroundColor(stateService: IStateService): string {
if (isWindows && systemPreferences.isInvertedColorScheme()) {
diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts
index e0e46e1b08f..d0184727757 100644
--- a/src/vs/code/electron-main/window.ts
+++ b/src/vs/code/electron-main/window.ts
@@ -273,7 +273,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// inform all waiting promises that we are ready now
while (this.whenReadyCallbacks.length) {
- this.whenReadyCallbacks.pop()(this);
+ this.whenReadyCallbacks.pop()!(this);
}
}
@@ -543,12 +543,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
}
- reload(configuration?: IWindowConfiguration, cli?: ParsedArgs): void {
-
+ reload(configurationIn?: IWindowConfiguration, cli?: ParsedArgs): void {
// If config is not provided, copy our current one
- if (!configuration) {
- configuration = objects.mixin({}, this.currentConfig);
- }
+ const configuration = configurationIn ? configurationIn : objects.mixin({}, this.currentConfig);
// Delete some properties we do not want during reload
delete configuration.filesToOpen;
@@ -713,7 +710,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return state;
}
- private validateWindowState(state: IWindowState): IWindowState {
+ private validateWindowState(state: IWindowState): IWindowState | null {
if (!state) {
return null;
}
@@ -856,6 +853,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return true; // default
}
+ if (windowConfig.nativeTabs) {
+ return true; // https://github.com/electron/electron/issues/16142
+ }
+
return windowConfig.nativeFullScreen !== false;
}
@@ -1028,7 +1029,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private createTouchBarGroupSegments(items: ISerializableCommandAction[] = []): ITouchBarSegment[] {
const segments: ITouchBarSegment[] = items.map(item => {
- let icon: Electron.NativeImage;
+ let icon: Electron.NativeImage | undefined;
if (item.iconLocation && item.iconLocation.dark.scheme === 'file') {
icon = nativeImage.createFromPath(URI.revive(item.iconLocation.dark).fsPath);
if (icon.isEmpty()) {
diff --git a/src/vs/code/node/windowsFinder.ts b/src/vs/code/node/windowsFinder.ts
index 8541b69dbe5..4c1765657de 100644
--- a/src/vs/code/node/windowsFinder.ts
+++ b/src/vs/code/node/windowsFinder.ts
@@ -26,7 +26,7 @@ export interface IBestWindowOrFolderOptions {
fileUri?: URI;
userHome?: string;
codeSettingsFolder?: string;
- workspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace;
+ workspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null;
}
export function findBestWindowOrFolderForFile({ windows, newWindow, reuseWindow, context, fileUri, workspaceResolver }: IBestWindowOrFolderOptions): W | null {
@@ -39,7 +39,7 @@ export function findBestWindowOrFolderForFile({ windows
return !newWindow ? getLastActiveWindow(windows) : null;
}
-function findWindowOnFilePath(windows: W[], fileUri: URI, workspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace): W | null {
+function findWindowOnFilePath(windows: W[], fileUri: URI, workspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): W | null {
// First check for windows with workspaces that have a parent folder of the provided path opened
const workspaceWindows = windows.filter(window => !!window.openedWorkspace);
diff --git a/src/vs/code/test/node/windowsFinder.test.ts b/src/vs/code/test/node/windowsFinder.test.ts
index 0c04c5b2cf5..bd9e7ee187a 100644
--- a/src/vs/code/test/node/windowsFinder.test.ts
+++ b/src/vs/code/test/node/windowsFinder.test.ts
@@ -31,7 +31,7 @@ function options(custom?: Partial>): I
}
const vscodeFolderWindow: ISimpleWindow = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder')) };
-const lastActiveWindow: ISimpleWindow = { lastFocusTime: 3, openedFolderUri: null };
+const lastActiveWindow: ISimpleWindow = { lastFocusTime: 3, openedFolderUri: undefined };
const noVscodeFolderWindow: ISimpleWindow = { lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) };
const windows: ISimpleWindow[] = [
vscodeFolderWindow,
diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
index df80f0b2087..8ead82c249a 100644
--- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
+++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
@@ -48,6 +48,7 @@ export class EditorScrollbar extends ViewPart {
handleMouseWheel: configScrollbarOpts.handleMouseWheel,
arrowSize: configScrollbarOpts.arrowSize,
mouseWheelScrollSensitivity: configScrollbarOpts.mouseWheelScrollSensitivity,
+ fastScrollSensitivity: configScrollbarOpts.fastScrollSensitivity,
};
this.scrollbar = this._register(new SmoothScrollableElement(linesContent.domNode, scrollbarOptions, this._context.viewLayout.scrollable));
@@ -127,7 +128,8 @@ export class EditorScrollbar extends ViewPart {
const editor = this._context.configuration.editor;
let newOpts: ScrollableElementChangeOptions = {
handleMouseWheel: editor.viewInfo.scrollbar.handleMouseWheel,
- mouseWheelScrollSensitivity: editor.viewInfo.scrollbar.mouseWheelScrollSensitivity
+ mouseWheelScrollSensitivity: editor.viewInfo.scrollbar.mouseWheelScrollSensitivity,
+ fastScrollSensitivity: editor.viewInfo.scrollbar.fastScrollSensitivity
};
this.scrollbar.updateOptions(newOpts);
}
diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts
index 8fa09be3b70..7974ee1a03f 100644
--- a/src/vs/editor/common/config/commonEditorConfig.ts
+++ b/src/vs/editor/common/config/commonEditorConfig.ts
@@ -33,7 +33,7 @@ export interface ITabFocus {
export const TabFocus: ITabFocus = new class implements ITabFocus {
private _tabFocus: boolean = false;
- private readonly _onDidChangeTabFocus: Emitter = new Emitter();
+ private readonly _onDidChangeTabFocus = new Emitter();
public readonly onDidChangeTabFocus: Event = this._onDidChangeTabFocus.event;
public getTabFocusMode(): boolean {
@@ -429,6 +429,11 @@ const editorConfiguration: IConfigurationNode = {
'default': EDITOR_DEFAULTS.viewInfo.scrollbar.mouseWheelScrollSensitivity,
'markdownDescription': nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.")
},
+ 'editor.fastScrollSensitivity': {
+ 'type': 'number',
+ 'default': EDITOR_DEFAULTS.viewInfo.scrollbar.fastScrollSensitivity,
+ 'markdownDescription': nls.localize('fastScrollSensitivity', "Scrolling speed mulitiplier when pressing `Alt`")
+ },
'editor.multiCursorModifier': {
'type': 'string',
'enum': ['ctrlCmd', 'alt'],
diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts
index ecdb1f39f45..bef7f91cd4e 100644
--- a/src/vs/editor/common/config/editorOptions.ts
+++ b/src/vs/editor/common/config/editorOptions.ts
@@ -458,6 +458,11 @@ export interface IEditorOptions {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
+ /**
+ * FastScrolling mulitplier speed when pressing `Alt`
+ * Defaults to 5.
+ */
+ fastScrollSensitivity?: number;
/**
* The modifier to be used to add multiple cursors with the mouse.
* Defaults to 'alt'
@@ -875,6 +880,7 @@ export interface InternalEditorScrollbarOptions {
readonly verticalScrollbarSize: number;
readonly verticalSliderSize: number;
readonly mouseWheelScrollSensitivity: number;
+ readonly fastScrollSensitivity: number;
}
export interface InternalEditorMinimapOptions {
@@ -1292,6 +1298,7 @@ export class InternalEditorOptions {
&& a.verticalScrollbarSize === b.verticalScrollbarSize
&& a.verticalSliderSize === b.verticalSliderSize
&& a.mouseWheelScrollSensitivity === b.mouseWheelScrollSensitivity
+ && a.fastScrollSensitivity === b.fastScrollSensitivity
);
}
@@ -1795,7 +1802,7 @@ export class EditorOptionsValidator {
};
}
- private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number): InternalEditorScrollbarOptions {
+ private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number, fastScrollSensitivity: number): InternalEditorScrollbarOptions {
if (typeof opts !== 'object') {
return defaults;
}
@@ -1818,7 +1825,8 @@ export class EditorOptionsValidator {
verticalSliderSize: _clampedInt(opts.verticalSliderSize, verticalScrollbarSize, 0, 1000),
handleMouseWheel: _boolean(opts.handleMouseWheel, defaults.handleMouseWheel),
- mouseWheelScrollSensitivity: mouseWheelScrollSensitivity
+ mouseWheelScrollSensitivity: mouseWheelScrollSensitivity,
+ fastScrollSensitivity: fastScrollSensitivity,
};
}
@@ -1965,7 +1973,12 @@ export class EditorOptionsValidator {
// Disallow 0, as it would prevent/block scrolling
mouseWheelScrollSensitivity = 1;
}
- const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity);
+
+ let fastScrollSensitivity = _float(opts.fastScrollSensitivity, defaults.scrollbar.fastScrollSensitivity);
+ if (fastScrollSensitivity <= 0) {
+ fastScrollSensitivity = defaults.scrollbar.fastScrollSensitivity;
+ }
+ const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity, fastScrollSensitivity);
const minimap = this._sanitizeMinimapOpts(opts.minimap, defaults.minimap);
return {
@@ -2592,6 +2605,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
verticalSliderSize: 14,
handleMouseWheel: true,
mouseWheelScrollSensitivity: 1,
+ fastScrollSensitivity: 5,
},
minimap: {
enabled: true,
diff --git a/src/vs/editor/common/config/editorZoom.ts b/src/vs/editor/common/config/editorZoom.ts
index 1be9203a573..522cfa6e095 100644
--- a/src/vs/editor/common/config/editorZoom.ts
+++ b/src/vs/editor/common/config/editorZoom.ts
@@ -15,7 +15,7 @@ export const EditorZoom: IEditorZoom = new class implements IEditorZoom {
private _zoomLevel: number = 0;
- private readonly _onDidChangeZoomLevel: Emitter = new Emitter();
+ private readonly _onDidChangeZoomLevel = new Emitter();
public readonly onDidChangeZoomLevel: Event = this._onDidChangeZoomLevel.event;
public getZoomLevel(): number {
diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts
index 50c6663b7fe..0efcb9559f4 100644
--- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts
+++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts
@@ -177,7 +177,7 @@ export class LanguageConfigurationRegistryImpl {
private _entries: RichEditSupport[];
- private readonly _onDidChange: Emitter = new Emitter();
+ private readonly _onDidChange = new Emitter();
public readonly onDidChange: Event = this._onDidChange.event;
constructor() {
diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts
index 616a4a40d98..1426b5e581e 100644
--- a/src/vs/editor/common/modes/languageFeatureRegistry.ts
+++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts
@@ -30,7 +30,7 @@ export class LanguageFeatureRegistry {
private _clock: number = 0;
private _entries: Entry[] = [];
- private readonly _onDidChange: Emitter = new Emitter();
+ private readonly _onDidChange = new Emitter();
constructor() {
}
diff --git a/src/vs/editor/common/modes/modesRegistry.ts b/src/vs/editor/common/modes/modesRegistry.ts
index a91dfa7887a..21b81b383ec 100644
--- a/src/vs/editor/common/modes/modesRegistry.ts
+++ b/src/vs/editor/common/modes/modesRegistry.ts
@@ -20,7 +20,7 @@ export class EditorModesRegistry {
private _languages: ILanguageExtensionPoint[];
private _dynamicLanguages: ILanguageExtensionPoint[];
- private readonly _onDidChangeLanguages: Emitter = new Emitter();
+ private readonly _onDidChangeLanguages = new Emitter();
public readonly onDidChangeLanguages: Event = this._onDidChangeLanguages.event;
constructor() {
diff --git a/src/vs/editor/common/modes/tokenizationRegistry.ts b/src/vs/editor/common/modes/tokenizationRegistry.ts
index f685c7c02cc..158608f91e4 100644
--- a/src/vs/editor/common/modes/tokenizationRegistry.ts
+++ b/src/vs/editor/common/modes/tokenizationRegistry.ts
@@ -13,7 +13,7 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
private _map: { [language: string]: ITokenizationSupport };
private _promises: { [language: string]: Thenable };
- private readonly _onDidChange: Emitter = new Emitter();
+ private readonly _onDidChange = new Emitter();
public readonly onDidChange: Event = this._onDidChange.event;
private _colorMap: Color[] | null;
diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts
index 21c4b0ce7a9..db3cd258a1f 100644
--- a/src/vs/editor/common/services/modeServiceImpl.ts
+++ b/src/vs/editor/common/services/modeServiceImpl.ts
@@ -45,10 +45,10 @@ export class ModeServiceImpl implements IModeService {
private readonly _instantiatedModes: { [modeId: string]: IMode; };
private readonly _registry: LanguagesRegistry;
- private readonly _onDidCreateMode: Emitter = new Emitter();
+ private readonly _onDidCreateMode = new Emitter();
public readonly onDidCreateMode: Event = this._onDidCreateMode.event;
- protected readonly _onLanguagesMaybeChanged: Emitter = new Emitter();
+ protected readonly _onLanguagesMaybeChanged = new Emitter();
private readonly onLanguagesMaybeChanged: Event = this._onLanguagesMaybeChanged.event;
constructor(warnOnOverwrite = false) {
diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts
index 9f37823db53..8cf29738393 100644
--- a/src/vs/editor/common/services/modelServiceImpl.ts
+++ b/src/vs/editor/common/services/modelServiceImpl.ts
@@ -268,7 +268,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
private readonly _onModelRemoved: Emitter = this._register(new Emitter());
public readonly onModelRemoved: Event = this._onModelRemoved.event;
- private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>({ leakWarningThreshold: 500 }));
+ private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>());
public readonly onModelModeChanged: Event<{ model: ITextModel; oldModeId: string; }> = this._onModelModeChanged.event;
private _modelCreationOptionsByLanguageAndResource: {
@@ -294,6 +294,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
if (this._markerService) {
this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this);
+ this._handleMarkerChange(this._markerService.read().map(m => m.resource));
}
this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions());
diff --git a/src/vs/editor/common/services/resolverService.ts b/src/vs/editor/common/services/resolverService.ts
index 09ac4bbcf61..28aca391a32 100644
--- a/src/vs/editor/common/services/resolverService.ts
+++ b/src/vs/editor/common/services/resolverService.ts
@@ -24,6 +24,11 @@ export interface ITextModelService {
* Registers a specific `scheme` content provider.
*/
registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable;
+
+ /**
+ * Check if a provider for the given `scheme` exists
+ */
+ hasTextModelContentProvider(scheme: string): boolean;
}
export interface ITextModelContentProvider {
diff --git a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts
index a32458d6abd..e9c0c51499a 100644
--- a/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts
+++ b/src/vs/editor/contrib/comment/test/lineCommentCommand.test.ts
@@ -950,7 +950,9 @@ suite('Editor Contrib - Line Comment in mixed modes', () => {
this._register(modes.TokenizationRegistry.register(this.getLanguageIdentifier().language, {
getInitialState: (): modes.IState => NULL_STATE,
- tokenize: undefined,
+ tokenize: () => {
+ throw new Error('not implemented');
+ },
tokenize2: (line: string, state: modes.IState): TokenizationResult2 => {
let languageId = (/^ /.test(line) ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID);
diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts
index 7e4c3823b3f..d38634e75cf 100644
--- a/src/vs/editor/contrib/contextmenu/contextmenu.ts
+++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts
@@ -46,7 +46,7 @@ export class ContextMenuController implements IEditorContribution {
this._toDispose.push(this._editor.onContextMenu((e: IEditorMouseEvent) => this._onContextMenu(e)));
this._toDispose.push(this._editor.onDidScrollChange((e: IScrollEvent) => {
- if (this._contextMenuIsBeingShownCount > 0) {
+ if (this._contextMenuIsBeingShownCount > 0 && e.scrollTopChanged) {
this._contextViewService.hideContextView();
}
}));
diff --git a/src/vs/editor/contrib/format/format.ts b/src/vs/editor/contrib/format/format.ts
index 0f510fde91e..401a6fc3fc0 100644
--- a/src/vs/editor/contrib/format/format.ts
+++ b/src/vs/editor/contrib/format/format.ts
@@ -17,11 +17,15 @@ import { CancellationToken } from 'vs/base/common/cancellation';
export class NoProviderError extends Error {
- static readonly Name = 'NOPRO';
+ static is(thing: any): thing is NoProviderError {
+ return thing instanceof Error && thing.name === NoProviderError._name;
+ }
+
+ private static readonly _name = 'NOPRO';
constructor(message?: string) {
super();
- this.name = NoProviderError.Name;
+ this.name = NoProviderError._name;
if (message) {
this.message = message;
}
diff --git a/src/vs/editor/contrib/format/formatActions.ts b/src/vs/editor/contrib/format/formatActions.ts
index 24c0b50385a..fef43d6243c 100644
--- a/src/vs/editor/contrib/format/formatActions.ts
+++ b/src/vs/editor/contrib/format/formatActions.ts
@@ -9,9 +9,9 @@ import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
-import { registerEditorAction, ServicesAccessor, EditorAction, registerEditorContribution, IActionOptions } from 'vs/editor/browser/editorExtensions';
-import { OnTypeFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
-import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits, NoProviderError } from 'vs/editor/contrib/format/format';
+import { registerEditorAction, ServicesAccessor, EditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
+import { OnTypeFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, DocumentFormattingEditProviderRegistry, FormattingOptions } from 'vs/editor/common/modes';
+import { getOnTypeFormattingEdits, NoProviderError } from 'vs/editor/contrib/format/format';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
@@ -21,12 +21,12 @@ import { Range } from 'vs/editor/common/core/range';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
-import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
+import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CancellationToken } from 'vs/base/common/cancellation';
-
+import { sequence } from 'vs/base/common/async';
function alertFormattingEdits(edits: ISingleEditOperation[]): void {
@@ -55,6 +55,98 @@ function alertFormattingEdits(edits: ISingleEditOperation[]): void {
}
}
+export const enum FormatRangeType {
+ Full,
+ Selection,
+}
+
+export function formatDocumentRange(workerService: IEditorWorkerService, editor: IActiveCodeEditor, rangeOrRangeType: Range | FormatRangeType, options: FormattingOptions, token: CancellationToken): Promise {
+
+ const provider = DocumentRangeFormattingEditProviderRegistry.ordered(editor.getModel()).slice(0, 1);
+ if (provider.length === 0) {
+ return Promise.reject(new NoProviderError());
+ }
+
+ let allEdits: ISingleEditOperation[] = [];
+
+ editor.pushUndoStop();
+ return sequence(provider.map(provider => {
+ // create a formatting task per provider. they run sequentially,
+ // potentially undoing the working of a previous formatter
+ return () => {
+ const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
+ const model = editor.getModel();
+
+ let range: Range;
+ if (rangeOrRangeType === FormatRangeType.Full) {
+ // full
+ range = model.getFullModelRange();
+
+ } else if (rangeOrRangeType === FormatRangeType.Selection) {
+ // selection or line (when empty)
+ range = editor.getSelection();
+ if (range.isEmpty()) {
+ range = new Range(range.startLineNumber, 1, range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
+ }
+ } else {
+ // as is
+ range = rangeOrRangeType;
+ }
+ return Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).then(edits => {
+ // break edits into smaller edits
+ return workerService.computeMoreMinimalEdits(editor.getModel().uri, edits);
+ }).then(edits => {
+ // make edit only when the editor didn't change while
+ // computing and only when there are edits
+ if (state.validate(editor) && isNonEmptyArray(edits)) {
+ FormattingEdit.execute(editor, edits);
+ allEdits = allEdits.concat(edits);
+ }
+ });
+ };
+ })).then(() => {
+ alertFormattingEdits(allEdits);
+ editor.pushUndoStop();
+ editor.focus();
+ editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
+ });
+}
+
+export function formatDocument(workerService: IEditorWorkerService, editor: IActiveCodeEditor, options: FormattingOptions, token: CancellationToken): Promise {
+ const provider = DocumentFormattingEditProviderRegistry.ordered(editor.getModel()).slice(0);
+ if (provider.length === 0) {
+ return formatDocumentRange(workerService, editor, FormatRangeType.Full, options, token);
+ }
+
+ let allEdits: ISingleEditOperation[] = [];
+
+ editor.pushUndoStop();
+ return sequence(provider.map(provider => {
+ // create a formatting task per provider. they run sequentially,
+ // potentially undoing the working of a previous formatter
+ return () => {
+ const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
+ const model = editor.getModel();
+ return Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).then(edits => {
+ // break edits into smaller edits
+ return workerService.computeMoreMinimalEdits(editor.getModel().uri, edits);
+ }).then(edits => {
+ // make edit only when the editor didn't change while
+ // computing and only when there are edits
+ if (state.validate(editor) && isNonEmptyArray(edits)) {
+ FormattingEdit.execute(editor, edits);
+ allEdits = allEdits.concat(edits);
+ }
+ });
+ };
+ })).then(() => {
+ alertFormattingEdits(allEdits);
+ editor.pushUndoStop();
+ editor.focus();
+ editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
+ });
+}
+
class FormatOnType implements editorCommon.IEditorContribution {
private static readonly ID = 'editor.contrib.autoFormat';
@@ -224,8 +316,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
let model = this.editor.getModel();
// no support
- let [support] = DocumentRangeFormattingEditProviderRegistry.ordered(model);
- if (!support || !support.provideDocumentRangeFormattingEdits) {
+ if (!DocumentRangeFormattingEditProviderRegistry.has(model)) {
return;
}
@@ -245,19 +336,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
const model = this.editor.getModel();
const { tabSize, insertSpaces } = model.getOptions();
- const state = new EditorState(this.editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
-
- getDocumentRangeFormattingEdits(model, range, { tabSize, insertSpaces }, CancellationToken.None).then(edits => {
- return this.workerService.computeMoreMinimalEdits(model.uri, edits);
- }).then(edits => {
- if (!state.validate(this.editor)) {
- return;
- }
- if (isNonEmptyArray(edits)) {
- FormattingEdit.execute(this.editor, edits);
- alertFormattingEdits(edits);
- }
- });
+ formatDocumentRange(this.workerService, this.editor, range, { tabSize, insertSpaces }, CancellationToken.None);
}
public getId(): string {
@@ -270,53 +349,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
}
}
-export abstract class AbstractFormatAction extends EditorAction {
-
- public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise {
- if (!editor.hasModel()) {
- return Promise.resolve(void 0);
- }
-
- const workerService = accessor.get(IEditorWorkerService);
- const notificationService = accessor.get(INotificationService);
-
- const formattingPromise = this._getFormattingEdits(editor, CancellationToken.None);
- if (!formattingPromise) {
- return Promise.resolve(void 0);
- }
-
- // Capture the state of the editor
- const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
-
- // Receive formatted value from worker
- return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits)).then(edits => {
- if (!state.validate(editor)) {
- return;
- }
-
- if (isNonEmptyArray(edits)) {
- FormattingEdit.execute(editor, edits);
- alertFormattingEdits(edits);
- editor.focus();
- editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
- }
- }, err => {
- if (err instanceof Error && err.name === NoProviderError.Name) {
- this._notifyNoProviderError(notificationService, editor.getModel().getLanguageIdentifier().language);
- } else {
- throw err;
- }
- });
- }
-
- protected abstract _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise | undefined;
-
- protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
- notificationService.info(nls.localize('no.provider', "There is no formatter for '{0}'-files installed.", language));
- }
-}
-
-export class FormatDocumentAction extends AbstractFormatAction {
+export class FormatDocumentAction extends EditorAction {
constructor() {
super({
@@ -339,21 +372,22 @@ export class FormatDocumentAction extends AbstractFormatAction {
});
}
- protected _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise | undefined {
+ run(accessor: ServicesAccessor, editor: ICodeEditor): Promise | void {
if (!editor.hasModel()) {
- return undefined;
+ return;
}
- const model = editor.getModel();
- const { tabSize, insertSpaces } = model.getOptions();
- return getDocumentFormattingEdits(model, { tabSize, insertSpaces }, token);
- }
-
- protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
- notificationService.info(nls.localize('no.documentprovider', "There is no document formatter for '{0}'-files installed.", language));
+ const notificationService = accessor.get(INotificationService);
+ const workerService = accessor.get(IEditorWorkerService);
+ const { tabSize, insertSpaces } = editor.getModel().getOptions();
+ return formatDocument(workerService, editor, { tabSize, insertSpaces }, CancellationToken.None).catch(err => {
+ if (NoProviderError.is(err)) {
+ notificationService.info(nls.localize('no.documentprovider', "There is no document formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language));
+ }
+ });
}
}
-export class FormatSelectionAction extends AbstractFormatAction {
+export class FormatSelectionAction extends EditorAction {
constructor() {
super({
@@ -374,24 +408,18 @@ export class FormatSelectionAction extends AbstractFormatAction {
});
}
- protected _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise | undefined {
+ run(accessor: ServicesAccessor, editor: ICodeEditor): Promise | void {
if (!editor.hasModel()) {
- return undefined;
+ return;
}
-
- const model = editor.getModel();
- let selection = editor.getSelection();
- if (selection.isEmpty()) {
- const maxColumn = model.getLineMaxColumn(selection.startLineNumber);
- selection = selection.setStartPosition(selection.startLineNumber, 1);
- selection = selection.setEndPosition(selection.endLineNumber, maxColumn);
- }
- const { tabSize, insertSpaces } = model.getOptions();
- return getDocumentRangeFormattingEdits(model, selection, { tabSize, insertSpaces }, token);
- }
-
- protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
- notificationService.info(nls.localize('no.selectionprovider', "There is no selection formatter for '{0}'-files installed.", language));
+ const notificationService = accessor.get(INotificationService);
+ const workerService = accessor.get(IEditorWorkerService);
+ const { tabSize, insertSpaces } = editor.getModel().getOptions();
+ return formatDocumentRange(workerService, editor, FormatRangeType.Selection, { tabSize, insertSpaces }, CancellationToken.None).catch(err => {
+ if (NoProviderError.is(err)) {
+ notificationService.info(nls.localize('no.selectionprovider', "There is no selection formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language));
+ }
+ });
}
}
@@ -404,25 +432,15 @@ registerEditorAction(FormatSelectionAction);
// and we keep it here such that existing keybinding configurations etc will still work
CommandsRegistry.registerCommand('editor.action.format', accessor => {
const editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
- if (editor) {
- return new class extends AbstractFormatAction {
- constructor() {
- super({} as IActionOptions);
- }
- _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise | undefined {
- if (!editor.hasModel()) {
- return undefined;
- }
-
- const model = editor.getModel();
- const editorSelection = editor.getSelection();
- const { tabSize, insertSpaces } = model.getOptions();
-
- return editorSelection.isEmpty()
- ? getDocumentFormattingEdits(model, { tabSize, insertSpaces }, token)
- : getDocumentRangeFormattingEdits(model, editorSelection, { tabSize, insertSpaces }, token);
- }
- }().run(accessor, editor);
+ if (!editor || !editor.hasModel()) {
+ return undefined;
+ }
+ const { tabSize, insertSpaces } = editor.getModel().getOptions();
+ const workerService = accessor.get(IEditorWorkerService);
+
+ if (editor.getSelection().isEmpty()) {
+ return formatDocument(workerService, editor, { tabSize, insertSpaces }, CancellationToken.None);
+ } else {
+ return formatDocumentRange(workerService, editor, FormatRangeType.Selection, { tabSize, insertSpaces }, CancellationToken.None);
}
- return undefined;
});
diff --git a/src/vs/editor/contrib/parameterHints/parameterHints.ts b/src/vs/editor/contrib/parameterHints/parameterHints.ts
index c9104b79c65..2a6ac351cd9 100644
--- a/src/vs/editor/contrib/parameterHints/parameterHints.ts
+++ b/src/vs/editor/contrib/parameterHints/parameterHints.ts
@@ -12,10 +12,11 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
-import { ParameterHintsWidget, TriggerContext } from './parameterHintsWidget';
+import { ParameterHintsWidget } from './parameterHintsWidget';
import { Context } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import * as modes from 'vs/editor/common/modes';
+import { TriggerContext } from 'vs/editor/contrib/parameterHints/parameterHintsModel';
class ParameterHintsController implements IEditorContribution {
diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts b/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts
new file mode 100644
index 00000000000..a071dabec1a
--- /dev/null
+++ b/src/vs/editor/contrib/parameterHints/parameterHintsModel.ts
@@ -0,0 +1,261 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async';
+import { onUnexpectedError } from 'vs/base/common/errors';
+import { Emitter } from 'vs/base/common/event';
+import { Disposable } from 'vs/base/common/lifecycle';
+import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
+import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
+import { CharacterSet } from 'vs/editor/common/core/characterClassifier';
+import * as modes from 'vs/editor/common/modes';
+import { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
+
+export interface TriggerContext {
+ readonly triggerKind: modes.SignatureHelpTriggerKind;
+ readonly triggerCharacter?: string;
+}
+
+const DefaultState = new class { readonly state = 'default'; };
+const PendingState = new class { readonly state = 'pending'; };
+
+class ActiveState {
+ readonly state = 'active';
+ constructor(
+ readonly hints: modes.SignatureHelp
+ ) { }
+}
+
+type ParameterHintState = typeof DefaultState | typeof PendingState | ActiveState;
+
+export class ParameterHintsModel extends Disposable {
+
+ private static readonly DEFAULT_DELAY = 120; // ms
+
+ private readonly _onChangedHints = this._register(new Emitter());
+ public readonly onChangedHints = this._onChangedHints.event;
+
+ private editor: ICodeEditor;
+ private enabled: boolean;
+ private state: ParameterHintState = DefaultState;
+ private triggerChars = new CharacterSet();
+ private retriggerChars = new CharacterSet();
+
+ private throttledDelayer: Delayer;
+ private provideSignatureHelpRequest?: CancelablePromise;
+ private triggerId = 0;
+
+ constructor(
+ editor: ICodeEditor,
+ delay: number = ParameterHintsModel.DEFAULT_DELAY
+ ) {
+ super();
+
+ this.editor = editor;
+ this.enabled = false;
+
+ this.throttledDelayer = new Delayer(delay);
+
+ this._register(this.editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()));
+ this._register(this.editor.onDidChangeModel(e => this.onModelChanged()));
+ this._register(this.editor.onDidChangeModelLanguage(_ => this.onModelChanged()));
+ this._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e)));
+ this._register(this.editor.onDidChangeModelContent(e => this.onModelContentChange()));
+ this._register(modes.SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this));
+ this._register(this.editor.onDidType(text => this.onDidType(text)));
+
+ this.onEditorConfigurationChange();
+ this.onModelChanged();
+ }
+
+ cancel(silent: boolean = false): void {
+ this.state = DefaultState;
+
+ this.throttledDelayer.cancel();
+
+ if (!silent) {
+ this._onChangedHints.fire(undefined);
+ }
+
+ if (this.provideSignatureHelpRequest) {
+ this.provideSignatureHelpRequest.cancel();
+ this.provideSignatureHelpRequest = undefined;
+ }
+ }
+
+ trigger(context: TriggerContext, delay?: number): void {
+ const model = this.editor.getModel();
+ if (model === null || !modes.SignatureHelpProviderRegistry.has(model)) {
+ return;
+ }
+
+ const triggerId = ++this.triggerId;
+ this.throttledDelayer.trigger(
+ () => this.doTrigger({
+ triggerKind: context.triggerKind,
+ triggerCharacter: context.triggerCharacter,
+ isRetrigger: this.state.state === 'active' || this.state.state === 'pending',
+ }, triggerId), delay).then(undefined, onUnexpectedError);
+ }
+
+ public next(): void {
+ if (this.state.state !== 'active') {
+ return;
+ }
+
+ const length = this.state.hints.signatures.length;
+ const activeSignature = this.state.hints.activeSignature;
+ const last = (activeSignature % length) === (length - 1);
+ const cycle = this.editor.getConfiguration().contribInfo.parameterHints.cycle;
+
+ // If there is only one signature, or we're on last signature of list
+ if ((length < 2 || last) && !cycle) {
+ this.cancel();
+ return;
+ }
+
+ this.updateActiveSignature(last && cycle ? 0 : activeSignature + 1);
+ }
+
+ public previous(): void {
+ if (this.state.state !== 'active') {
+ return;
+ }
+
+ const length = this.state.hints.signatures.length;
+ const activeSignature = this.state.hints.activeSignature;
+ const first = activeSignature === 0;
+ const cycle = this.editor.getConfiguration().contribInfo.parameterHints.cycle;
+
+ // If there is only one signature, or we're on first signature of list
+ if ((length < 2 || first) && !cycle) {
+ this.cancel();
+ return;
+ }
+
+ this.updateActiveSignature(first && cycle ? length - 1 : activeSignature - 1);
+ }
+
+ private updateActiveSignature(activeSignature: number) {
+ if (this.state.state !== 'active') {
+ return;
+ }
+
+ this.state = {
+ state: 'active',
+ hints: { ...this.state.hints, activeSignature }
+ };
+ this._onChangedHints.fire(this.state.hints);
+ }
+
+ private doTrigger(triggerContext: modes.SignatureHelpContext, triggerId: number): Promise {
+ this.cancel(true);
+
+ if (!this.editor.hasModel()) {
+ return Promise.resolve(false);
+ }
+
+ const model = this.editor.getModel();
+ const position = this.editor.getPosition();
+
+ this.state = PendingState;
+
+ this.provideSignatureHelpRequest = createCancelablePromise(token =>
+ provideSignatureHelp(model, position, triggerContext, token));
+
+ return this.provideSignatureHelpRequest.then(result => {
+ // Check that we are still resolving the correct signature help
+ if (triggerId !== this.triggerId) {
+ return false;
+ }
+
+ if (!result || !result.signatures || result.signatures.length === 0) {
+ this.cancel();
+ return false;
+ } else {
+ this.state = new ActiveState(result);
+ this._onChangedHints.fire(this.state.hints);
+ return true;
+ }
+ }).catch(error => {
+ this.state = DefaultState;
+ onUnexpectedError(error);
+ return false;
+ });
+ }
+
+ private get isTriggered(): boolean {
+ return this.state.state === 'active' || this.state.state === 'pending' || this.throttledDelayer.isTriggered();
+ }
+
+ private onModelChanged(): void {
+ this.cancel();
+
+ // Update trigger characters
+ this.triggerChars = new CharacterSet();
+ this.retriggerChars = new CharacterSet();
+
+ const model = this.editor.getModel();
+ if (!model) {
+ return;
+ }
+
+ for (const support of modes.SignatureHelpProviderRegistry.ordered(model)) {
+ for (const ch of support.signatureHelpTriggerCharacters || []) {
+ this.triggerChars.add(ch.charCodeAt(0));
+
+ // All trigger characters are also considered retrigger characters
+ this.retriggerChars.add(ch.charCodeAt(0));
+ }
+
+ for (const ch of support.signatureHelpRetriggerCharacters || []) {
+ this.retriggerChars.add(ch.charCodeAt(0));
+ }
+ }
+ }
+
+ private onDidType(text: string) {
+ if (!this.enabled) {
+ return;
+ }
+
+ const lastCharIndex = text.length - 1;
+ const triggerCharCode = text.charCodeAt(lastCharIndex);
+
+ if (this.triggerChars.has(triggerCharCode) || this.isTriggered && this.retriggerChars.has(triggerCharCode)) {
+ this.trigger({
+ triggerKind: modes.SignatureHelpTriggerKind.TriggerCharacter,
+ triggerCharacter: text.charAt(lastCharIndex),
+ });
+ }
+ }
+
+ private onCursorChange(e: ICursorSelectionChangedEvent): void {
+ if (e.source === 'mouse') {
+ this.cancel();
+ } else if (this.isTriggered) {
+ this.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });
+ }
+ }
+
+ private onModelContentChange(): void {
+ if (this.isTriggered) {
+ this.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });
+ }
+ }
+
+ private onEditorConfigurationChange(): void {
+ this.enabled = this.editor.getConfiguration().contribInfo.parameterHints.enabled;
+
+ if (!this.enabled) {
+ this.cancel();
+ }
+ }
+
+ dispose(): void {
+ this.cancel(true);
+ super.dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
index c4696af5f52..7d347210c2b 100644
--- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
+++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
@@ -3,232 +3,28 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import 'vs/css!./parameterHints';
-import * as nls from 'vs/nls';
-import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
-import * as aria from 'vs/base/browser/ui/aria/aria';
-import * as modes from 'vs/editor/common/modes';
-import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
-import { createCancelablePromise, CancelablePromise, Delayer } from 'vs/base/common/async';
-import { onUnexpectedError } from 'vs/base/common/errors';
-import { Event, Emitter } from 'vs/base/common/event';
import { domEvent, stop } from 'vs/base/browser/event';
-import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
-import { Context, provideSignatureHelp } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
+import * as aria from 'vs/base/browser/ui/aria/aria';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
-import { CharacterSet } from 'vs/editor/common/core/characterClassifier';
+import { Event } from 'vs/base/common/event';
+import { dispose, IDisposable } from 'vs/base/common/lifecycle';
+import 'vs/css!./parameterHints';
+import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
-import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
-import { registerThemingParticipant, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
-import { editorHoverBackground, editorHoverBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
-import { IOpenerService } from 'vs/platform/opener/common/opener';
+import * as modes from 'vs/editor/common/modes';
import { IModeService } from 'vs/editor/common/services/modeService';
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
+import { Context } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
+import * as nls from 'vs/nls';
+import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
+import { IOpenerService } from 'vs/platform/opener/common/opener';
+import { editorHoverBackground, editorHoverBorder, textCodeBlockBackground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
+import { HIGH_CONTRAST, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
+import { ParameterHintsModel, TriggerContext } from 'vs/editor/contrib/parameterHints/parameterHintsModel';
const $ = dom.$;
-export interface TriggerContext {
- readonly triggerKind: modes.SignatureHelpTriggerKind;
- readonly triggerCharacter?: string;
-}
-
-export interface IHintEvent {
- hints: modes.SignatureHelp;
-}
-
-export class ParameterHintsModel extends Disposable {
-
- private static readonly DEFAULT_DELAY = 120; // ms
-
- private readonly _onHint = this._register(new Emitter());
- public readonly onHint: Event = this._onHint.event;
-
- private readonly _onCancel = this._register(new Emitter());
- public readonly onCancel: Event = this._onCancel.event;
-
- private editor: ICodeEditor;
- private enabled: boolean;
- private triggerCharactersListeners: IDisposable[];
- private active: boolean = false;
- private pending: boolean = false;
- private triggerChars = new CharacterSet();
- private retriggerChars = new CharacterSet();
-
- private throttledDelayer: Delayer;
- private provideSignatureHelpRequest?: CancelablePromise;
-
- constructor(
- editor: ICodeEditor,
- delay: number = ParameterHintsModel.DEFAULT_DELAY
- ) {
- super();
-
- this.editor = editor;
- this.enabled = false;
- this.triggerCharactersListeners = [];
-
- this.throttledDelayer = new Delayer(delay);
-
- this._register(this.editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()));
- this._register(this.editor.onDidChangeModel(e => this.onModelChanged()));
- this._register(this.editor.onDidChangeModelLanguage(_ => this.onModelChanged()));
- this._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e)));
- this._register(this.editor.onDidChangeModelContent(e => this.onModelContentChange()));
- this._register(modes.SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this));
- this._register(this.editor.onDidType(text => this.onDidType(text)));
-
- this.onEditorConfigurationChange();
- this.onModelChanged();
- }
-
- cancel(silent: boolean = false): void {
- this.active = false;
- this.pending = false;
-
- this.throttledDelayer.cancel();
-
- if (!silent) {
- this._onCancel.fire(void 0);
- }
-
- if (this.provideSignatureHelpRequest) {
- this.provideSignatureHelpRequest.cancel();
- this.provideSignatureHelpRequest = undefined;
- }
- }
-
- trigger(context: TriggerContext, delay?: number): void {
-
- const model = this.editor.getModel();
- if (model === null || !modes.SignatureHelpProviderRegistry.has(model)) {
- return;
- }
-
- this.throttledDelayer.trigger(
- () => this.doTrigger({
- triggerKind: context.triggerKind,
- triggerCharacter: context.triggerCharacter,
- isRetrigger: this.isTriggered,
- }), delay).then(undefined, onUnexpectedError);
- }
-
- private doTrigger(triggerContext: modes.SignatureHelpContext): Promise {
- this.cancel(true);
-
- if (!this.editor.hasModel()) {
- return Promise.resolve(false);
- }
-
- const model = this.editor.getModel();
- const position = this.editor.getPosition();
-
- this.pending = true;
-
- this.provideSignatureHelpRequest = createCancelablePromise(token =>
- provideSignatureHelp(model!, position!, triggerContext, token));
-
- return this.provideSignatureHelpRequest.then(result => {
- this.pending = false;
-
- if (!result || !result.signatures || result.signatures.length === 0) {
- this.cancel();
- this._onCancel.fire(void 0);
- return false;
- }
-
- this.active = true;
- const event: IHintEvent = { hints: result };
- this._onHint.fire(event);
- return true;
-
- }).catch(error => {
- this.pending = false;
- onUnexpectedError(error);
- return false;
- });
- }
-
- private get isTriggered(): boolean {
- return this.active || this.pending || this.throttledDelayer.isTriggered();
- }
-
- private onModelChanged(): void {
- this.cancel();
-
- // Update trigger characters
- this.triggerChars = new CharacterSet();
- this.retriggerChars = new CharacterSet();
-
- const model = this.editor.getModel();
- if (!model) {
- return;
- }
-
- for (const support of modes.SignatureHelpProviderRegistry.ordered(model)) {
- if (Array.isArray(support.signatureHelpTriggerCharacters)) {
- for (const ch of support.signatureHelpTriggerCharacters) {
- this.triggerChars.add(ch.charCodeAt(0));
-
- // All trigger characters are also considered retrigger characters
- this.retriggerChars.add(ch.charCodeAt(0));
-
- }
- }
- if (Array.isArray(support.signatureHelpRetriggerCharacters)) {
- for (const ch of support.signatureHelpRetriggerCharacters) {
- this.retriggerChars.add(ch.charCodeAt(0));
- }
- }
- }
- }
-
- private onDidType(text: string) {
- if (!this.enabled) {
- return;
- }
-
- const lastCharIndex = text.length - 1;
- const triggerCharCode = text.charCodeAt(lastCharIndex);
-
- if (this.triggerChars.has(triggerCharCode) || this.isTriggered && this.retriggerChars.has(triggerCharCode)) {
- this.trigger({
- triggerKind: modes.SignatureHelpTriggerKind.TriggerCharacter,
- triggerCharacter: text.charAt(lastCharIndex),
- });
- }
- }
-
- private onCursorChange(e: ICursorSelectionChangedEvent): void {
- if (e.source === 'mouse') {
- this.cancel();
- } else if (this.isTriggered) {
- this.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });
- }
- }
-
- private onModelContentChange(): void {
- if (this.isTriggered) {
- this.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });
- }
- }
-
- private onEditorConfigurationChange(): void {
- this.enabled = this.editor.getConfiguration().contribInfo.parameterHints.enabled;
-
- if (!this.enabled) {
- this.cancel();
- }
- }
-
- dispose(): void {
- this.cancel(true);
- this.triggerCharactersListeners = dispose(this.triggerCharactersListeners);
-
- super.dispose();
- }
-}
-
export class ParameterHintsWidget implements IContentWidget, IDisposable {
private static readonly ID = 'editor.widget.parameterHintsWidget';
@@ -242,9 +38,7 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
private signature: HTMLElement;
private docs: HTMLElement;
private overloads: HTMLElement;
- private currentSignature: number;
private visible: boolean;
- private hints: modes.SignatureHelp | null;
private announcedLabel: string | null;
private scrollbar: DomScrollableElement;
private disposables: IDisposable[];
@@ -265,15 +59,13 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
this.visible = false;
this.disposables = [];
- this.disposables.push(this.model.onHint(e => {
- this.show();
- this.hints = e.hints;
- this.currentSignature = e.hints.activeSignature;
- this.render();
- }));
-
- this.disposables.push(this.model.onCancel(() => {
- this.hide();
+ this.disposables.push(this.model.onChangedHints(newParameterHints => {
+ if (newParameterHints) {
+ this.show();
+ this.render(newParameterHints);
+ } else {
+ this.hide();
+ }
}));
}
@@ -302,8 +94,6 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
this.docs = dom.append(body, $('.docs'));
- this.currentSignature = 0;
-
this.editor.addContentWidget(this);
this.hide();
@@ -355,7 +145,6 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
this.keyVisible.reset();
this.visible = false;
- this.hints = null;
this.announcedLabel = null;
dom.removeClass(this.element, 'visible');
this.editor.layoutContentWidget(this);
@@ -371,19 +160,15 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
return null;
}
- private render(): void {
- if (!this.hints) {
- return;
- }
-
- const multiple = this.hints.signatures.length > 1;
+ private render(hints: modes.SignatureHelp): void {
+ const multiple = hints.signatures.length > 1;
dom.toggleClass(this.element, 'multiple', multiple);
this.keyMultipleSignatures.set(multiple);
this.signature.innerHTML = '';
this.docs.innerHTML = '';
- const signature = this.hints.signatures[this.currentSignature];
+ const signature = hints.signatures[hints.activeSignature];
if (!signature) {
return;
@@ -401,13 +186,13 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
label.textContent = signature.label;
} else {
- this.renderParameters(code, signature, this.hints.activeParameter);
+ this.renderParameters(code, signature, hints.activeParameter);
}
dispose(this.renderDisposeables);
this.renderDisposeables = [];
- const activeParameter = signature.parameters[this.hints.activeParameter];
+ const activeParameter = signature.parameters[hints.activeParameter];
if (activeParameter && activeParameter.documentation) {
const documentation = $('span.documentation');
@@ -434,16 +219,16 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
dom.append(this.docs, renderedContents.element);
}
- let currentOverload = String(this.currentSignature + 1);
+ let currentOverload = String(hints.activeSignature + 1);
- if (this.hints.signatures.length < 10) {
- currentOverload += `/${this.hints.signatures.length}`;
+ if (hints.signatures.length < 10) {
+ currentOverload += `/${hints.signatures.length}`;
}
this.overloads.textContent = currentOverload;
if (activeParameter) {
- const labelToAnnounce = this.getParameterLabel(signature, this.hints.activeParameter);
+ const labelToAnnounce = this.getParameterLabel(signature, hints.activeParameter);
// Select method gets called on every user type while parameter hints are visible.
// We do not want to spam the user with same announcements, so we only announce if the current parameter changed.
@@ -497,85 +282,16 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
}
}
- // private select(position: number): void {
- // const signature = this.signatureViews[position];
-
- // if (!signature) {
- // return;
- // }
-
- // this.signatures.style.height = `${ signature.height }px`;
- // this.signatures.scrollTop = signature.top;
-
- // let overloads = '' + (position + 1);
-
- // if (this.signatureViews.length < 10) {
- // overloads += '/' + this.signatureViews.length;
- // }
-
- // this.overloads.textContent = overloads;
-
- // if (this.hints && this.hints.signatures[position].parameters[this.hints.activeParameter]) {
- // const labelToAnnounce = this.hints.signatures[position].parameters[this.hints.activeParameter].label;
- // // Select method gets called on every user type while parameter hints are visible.
- // // We do not want to spam the user with same announcements, so we only announce if the current parameter changed.
- // if (this.announcedLabel !== labelToAnnounce) {
- // aria.alert(nls.localize('hint', "{0}, hint", labelToAnnounce));
- // this.announcedLabel = labelToAnnounce;
- // }
- // }
-
- // this.editor.layoutContentWidget(this);
- // }
-
- next(): boolean {
- if (!this.hints) {
- return false;
+ next(): void {
+ if (this.model) {
+ this.model.next();
}
-
- const length = this.hints.signatures.length;
- const last = (this.currentSignature % length) === (length - 1);
- const cycle = this.editor.getConfiguration().contribInfo.parameterHints.cycle;
-
- // If there is only one signature, or we're on last signature of list
- if ((length < 2 || last) && !cycle) {
- this.cancel();
- return false;
- }
-
- if (last && cycle) {
- this.currentSignature = 0;
- } else {
- this.currentSignature++;
- }
-
- this.render();
- return true;
}
- previous(): boolean {
- if (!this.hints) {
- return false;
+ previous(): void {
+ if (this.model) {
+ this.model.previous();
}
-
- const length = this.hints.signatures.length;
- const first = this.currentSignature === 0;
- const cycle = this.editor.getConfiguration().contribInfo.parameterHints.cycle;
-
- // If there is only one signature, or we're on first signature of list
- if ((length < 2 || first) && !cycle) {
- this.cancel();
- return false;
- }
-
- if (first && cycle) {
- this.currentSignature = length - 1;
- } else {
- this.currentSignature--;
- }
-
- this.render();
- return true;
}
cancel(): void {
diff --git a/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
index 8d80428ad0f..ff1931ae1e5 100644
--- a/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
+++ b/src/vs/editor/contrib/parameterHints/test/parameterHintsModel.test.ts
@@ -17,7 +17,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
-import { ParameterHintsModel } from '../parameterHintsWidget';
+import { ParameterHintsModel } from 'vs/editor/contrib/parameterHints/parameterHintsModel';
const mockFile = URI.parse('test:somefile.ttt');
const mockFileSelector = { scheme: 'test' };
@@ -89,12 +89,13 @@ suite('ParameterHintsModel', () => {
if (invokeCount === 1) {
assert.strictEqual(context.triggerKind, modes.SignatureHelpTriggerKind.TriggerCharacter);
assert.strictEqual(context.triggerCharacter, triggerChar);
+ assert.strictEqual(context.isRetrigger, false);
// Retrigger
editor.trigger('keyboard', Handler.Type, { text: triggerChar });
} else {
assert.strictEqual(invokeCount, 2);
assert.strictEqual(context.triggerKind, modes.SignatureHelpTriggerKind.TriggerCharacter);
- assert.ok(context.isRetrigger);
+ assert.strictEqual(context.isRetrigger, true);
assert.strictEqual(context.triggerCharacter, triggerChar);
done();
}
@@ -122,6 +123,7 @@ suite('ParameterHintsModel', () => {
if (invokeCount === 1) {
assert.strictEqual(context.triggerKind, modes.SignatureHelpTriggerKind.TriggerCharacter);
assert.strictEqual(context.triggerCharacter, triggerChar);
+ assert.strictEqual(context.isRetrigger, false);
// Cancel and retrigger
hintModel.cancel();
@@ -130,6 +132,8 @@ suite('ParameterHintsModel', () => {
assert.strictEqual(invokeCount, 2);
assert.strictEqual(context.triggerKind, modes.SignatureHelpTriggerKind.TriggerCharacter);
assert.strictEqual(context.triggerCharacter, triggerChar);
+ assert.strictEqual(context.isRetrigger, false);
+
done();
}
return emptySigHelpResult;
@@ -244,10 +248,10 @@ suite('ParameterHintsModel', () => {
assert.strictEqual(-1, didRequestCancellationOf);
return new Promise((resolve, reject) =>
- hintsModel.onHint(e => {
+ hintsModel.onChangedHints(newParamterHints => {
try {
assert.strictEqual(0, didRequestCancellationOf);
- assert.strictEqual('1', e.hints.signatures[0].label);
+ assert.strictEqual('1', newParamterHints!.signatures[0].label);
resolve();
} catch (e) {
reject(e);
diff --git a/src/vs/editor/contrib/referenceSearch/referencesTree.ts b/src/vs/editor/contrib/referenceSearch/referencesTree.ts
index 73508ceaaa4..e9282d70092 100644
--- a/src/vs/editor/contrib/referenceSearch/referencesTree.ts
+++ b/src/vs/editor/contrib/referenceSearch/referencesTree.ts
@@ -20,7 +20,10 @@ import { escape } from 'vs/base/common/strings';
import { Disposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
-import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
+import { IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list';
+import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
+import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
+import { basename } from 'vs/base/common/paths';
//#region data source
@@ -75,6 +78,21 @@ export class Delegate implements IListVirtualDelegate {
}
}
+export class StringRepresentationProvider implements IKeyboardNavigationLabelProvider {
+
+ constructor(@IKeybindingService private readonly _keybindingService: IKeybindingService) { }
+
+ getKeyboardNavigationLabel(element: TreeElement): { toString(): string; } {
+ // todo@joao `OneReference` elements are lazy and their "real" label
+ // isn't known yet
+ return basename(element.uri.path);
+ }
+
+ mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
+ return this._keybindingService.mightProducePrintableCharacter(event);
+ }
+}
+
//#region render: File
class FileReferencesTemplate extends Disposable {
@@ -100,7 +118,7 @@ class FileReferencesTemplate extends Disposable {
set(element: FileReferences) {
let parent = dirname(element.uri);
- this.file.setValue(getBaseLabel(element.uri), parent ? this._uriLabel.getUriLabel(parent, { relative: true }) : undefined, { title: this._uriLabel.getUriLabel(element.uri) });
+ this.file.setLabel(getBaseLabel(element.uri), parent ? this._uriLabel.getUriLabel(parent, { relative: true }) : undefined, { title: this._uriLabel.getUriLabel(element.uri) });
const len = element.children.length;
this.badge.setCount(len);
if (element.failure) {
diff --git a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts
index 403567a3094..affb6a2eb52 100644
--- a/src/vs/editor/contrib/referenceSearch/referencesWidget.ts
+++ b/src/vs/editor/contrib/referenceSearch/referencesWidget.ts
@@ -21,7 +21,7 @@ import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/
import { ModelDecorationOptions, TextModel } from 'vs/editor/common/model/textModel';
import { Location } from 'vs/editor/common/modes';
import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
-import { AriaProvider, DataSource, Delegate, FileReferencesRenderer, OneReferenceRenderer, TreeElement } from 'vs/editor/contrib/referenceSearch/referencesTree';
+import { AriaProvider, DataSource, Delegate, FileReferencesRenderer, OneReferenceRenderer, TreeElement, StringRepresentationProvider } from 'vs/editor/contrib/referenceSearch/referencesTree';
import * as nls from 'vs/nls';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -353,7 +353,8 @@ export class ReferenceWidget extends PeekViewWidget {
const treeOptions = {
ariaLabel: nls.localize('treeAriaLabel', "References"),
keyboardSupport: this._defaultTreeKeyboardSupport,
- accessibilityProvider: new AriaProvider()
+ accessibilityProvider: new AriaProvider(),
+ keyboardNavigationLabelProvider: this._instantiationService.createInstance(StringRepresentationProvider)
};
const treeDataSource = this._instantiationService.createInstance(DataSource);
diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts
index df08a20b3a9..8db5ba1e17d 100644
--- a/src/vs/editor/contrib/snippet/snippetController2.ts
+++ b/src/vs/editor/contrib/snippet/snippetController2.ts
@@ -34,10 +34,10 @@ export class SnippetController2 implements IEditorContribution {
private readonly _hasNextTabstop: IContextKey;
private readonly _hasPrevTabstop: IContextKey;
- private _session: SnippetSession;
+ private _session?: SnippetSession;
private _snippetListener: IDisposable[] = [];
private _modelVersionId: number;
- private _currentChoice: Choice;
+ private _currentChoice?: Choice;
constructor(
private readonly _editor: ICodeEditor,
@@ -87,6 +87,9 @@ export class SnippetController2 implements IEditorContribution {
undoStopBefore: boolean = true, undoStopAfter: boolean = true,
adjustWhitespace: boolean = true,
): void {
+ if (!this._editor.hasModel()) {
+ return;
+ }
// don't listen while inserting the snippet
// as that is the inflight state causing cancelation
@@ -118,7 +121,7 @@ export class SnippetController2 implements IEditorContribution {
}
private _updateState(): void {
- if (!this._session) {
+ if (!this._session || !this._editor.hasModel()) {
// canceled in the meanwhile
return;
}
@@ -147,6 +150,11 @@ export class SnippetController2 implements IEditorContribution {
}
private _handleChoice(): void {
+ if (!this._session) {
+ this._currentChoice = undefined;
+ return;
+ }
+
const { choice } = this._session;
if (!choice) {
this._currentChoice = undefined;
@@ -196,12 +204,16 @@ export class SnippetController2 implements IEditorContribution {
}
prev(): void {
- this._session.prev();
+ if (this._session) {
+ this._session.prev();
+ }
this._updateState();
}
next(): void {
- this._session.next();
+ if (this._session) {
+ this._session.next();
+ }
this._updateState();
}
@@ -209,7 +221,7 @@ export class SnippetController2 implements IEditorContribution {
return this._inSnippet.get();
}
- getSessionEnclosingRange(): Range {
+ getSessionEnclosingRange(): Range | undefined {
if (this._session) {
return this._session.getEnclosingRange();
}
diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts
index 17bf8b96b3a..98c7d98d131 100644
--- a/src/vs/editor/contrib/snippet/snippetSession.ts
+++ b/src/vs/editor/contrib/snippet/snippetSession.ts
@@ -95,6 +95,9 @@ export class OneSnippet {
}
move(fwd: boolean | undefined): Selection[] {
+ if (!this._editor.hasModel()) {
+ return [];
+ }
this._initDecorations();
@@ -190,7 +193,7 @@ export class OneSnippet {
computePossibleSelections() {
const result = new Map();
for (const placeholdersWithEqualIndex of this._placeholderGroups) {
- let ranges: Range[];
+ let ranges: Range[] | undefined;
for (const placeholder of placeholdersWithEqualIndex) {
if (placeholder.isFinalTabstop) {
@@ -278,7 +281,7 @@ export class OneSnippet {
}
public getEnclosingRange(): Range {
- let result: Range;
+ let result: Range | undefined;
const model = this._editor.getModel();
this._placeholderDecorations.forEach((decorationId) => {
const placeholderRange = model.getDecorationRange(decorationId);
@@ -341,11 +344,14 @@ export class SnippetSession {
}
static createEditsAndSnippets(editor: ICodeEditor, template: string, overwriteBefore: number, overwriteAfter: number, enforceFinalTabstop: boolean, adjustWhitespace: boolean): { edits: IIdentifiedSingleEditOperation[], snippets: OneSnippet[] } {
-
- const model = editor.getModel();
const edits: IIdentifiedSingleEditOperation[] = [];
const snippets: OneSnippet[] = [];
+ if (!editor.hasModel()) {
+ return { edits, snippets };
+ }
+ const model = editor.getModel();
+
const modelBasedVariableResolver = new ModelBasedVariableResolver(model);
const clipboardService = editor.invokeWithinContext(accessor => accessor.get(IClipboardService, optional));
@@ -444,6 +450,9 @@ export class SnippetSession {
}
insert(): void {
+ if (!this._editor.hasModel()) {
+ return;
+ }
const model = this._editor.getModel();
@@ -463,6 +472,9 @@ export class SnippetSession {
}
merge(template: string, overwriteBefore: number = 0, overwriteAfter: number = 0, adjustWhitespace: boolean = true): void {
+ if (!this._editor.hasModel()) {
+ return;
+ }
this._templateMerges.push([this._snippets[0]._nestingLevel, this._snippets[0]._placeholderGroupsIdx, template]);
const { edits, snippets } = SnippetSession.createEditsAndSnippets(this._editor, template, overwriteBefore, overwriteAfter, true, adjustWhitespace);
@@ -596,7 +608,7 @@ export class SnippetSession {
}
public getEnclosingRange(): Range {
- let result: Range;
+ let result: Range | undefined;
for (const snippet of this._snippets) {
const snippetRange = snippet.getEnclosingRange();
if (!result) {
diff --git a/src/vs/editor/contrib/suggest/suggestModel.ts b/src/vs/editor/contrib/suggest/suggestModel.ts
index 763ca02bbf9..900f7b2d66b 100644
--- a/src/vs/editor/contrib/suggest/suggestModel.ts
+++ b/src/vs/editor/contrib/suggest/suggestModel.ts
@@ -104,9 +104,9 @@ export class SuggestModel implements IDisposable {
private _currentSelection: Selection;
private _completionModel?: CompletionModel;
- private readonly _onDidCancel: Emitter = new Emitter();
- private readonly _onDidTrigger: Emitter = new Emitter();
- private readonly _onDidSuggest: Emitter = new Emitter();
+ private readonly _onDidCancel = new Emitter();
+ private readonly _onDidTrigger = new Emitter();
+ private readonly _onDidSuggest = new Emitter();
readonly onDidCancel: Event = this._onDidCancel.event;
readonly onDidTrigger: Event = this._onDidTrigger.event;
diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts
index de7330e305e..ae57d64b7db 100644
--- a/src/vs/editor/contrib/suggest/suggestWidget.ts
+++ b/src/vs/editor/contrib/suggest/suggestWidget.ts
@@ -185,7 +185,7 @@ class Renderer implements IListRenderer
];
}
- data.iconLabel.setValue(suggestion.label, undefined, labelOptions);
+ data.iconLabel.setLabel(suggestion.label, undefined, labelOptions);
data.typeLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');
if (canExpandCompletionItem(element)) {
diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts
index 2a2b5dc59ad..84cc477a801 100644
--- a/src/vs/editor/standalone/browser/simpleServices.ts
+++ b/src/vs/editor/standalone/browser/simpleServices.ts
@@ -116,6 +116,10 @@ export class SimpleEditorModelResolverService implements ITextModelService {
};
}
+ public hasTextModelContentProvider(scheme: string): boolean {
+ return false;
+ }
+
private findModel(editor: ICodeEditor, resource: URI): ITextModel | null {
let model = editor.getModel();
if (model && model.uri.toString() !== resource.toString()) {
@@ -218,7 +222,7 @@ export class StandaloneCommandService implements ICommandService {
private readonly _instantiationService: IInstantiationService;
private _dynamicCommands: { [id: string]: ICommand; };
- private readonly _onWillExecuteCommand: Emitter = new Emitter();
+ private readonly _onWillExecuteCommand = new Emitter();
public readonly onWillExecuteCommand: Event = this._onWillExecuteCommand.event;
constructor(instantiationService: IInstantiationService) {
@@ -502,13 +506,13 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService {
private static SCHEME = 'inmemory';
- private readonly _onDidChangeWorkspaceName: Emitter = new Emitter();
+ private readonly _onDidChangeWorkspaceName = new Emitter();
public readonly onDidChangeWorkspaceName: Event = this._onDidChangeWorkspaceName.event;
- private readonly _onDidChangeWorkspaceFolders: Emitter = new Emitter();
+ private readonly _onDidChangeWorkspaceFolders = new Emitter();
public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event;
- private readonly _onDidChangeWorkbenchState: Emitter = new Emitter();
+ private readonly _onDidChangeWorkbenchState = new Emitter();
public readonly onDidChangeWorkbenchState: Event = this._onDidChangeWorkbenchState.event;
private readonly workspace: IWorkspace;
@@ -608,7 +612,7 @@ export class SimpleBulkEditService implements IBulkEditService {
export class SimpleUriLabelService implements ILabelService {
_serviceBrand: any;
- private readonly _onDidRegisterFormatter: Emitter = new Emitter();
+ private readonly _onDidRegisterFormatter = new Emitter();
public readonly onDidRegisterFormatter: Event = this._onDidRegisterFormatter.event;
public getUriLabel(resource: URI, options?: { relative?: boolean, forceNoTildify?: boolean }): string {
diff --git a/src/vs/editor/test/browser/editorTestServices.ts b/src/vs/editor/test/browser/editorTestServices.ts
index 31a6abfe92c..a4fd499a1f8 100644
--- a/src/vs/editor/test/browser/editorTestServices.ts
+++ b/src/vs/editor/test/browser/editorTestServices.ts
@@ -29,7 +29,7 @@ export class TestCommandService implements ICommandService {
private readonly _instantiationService: IInstantiationService;
- private readonly _onWillExecuteCommand: Emitter = new Emitter();
+ private readonly _onWillExecuteCommand = new Emitter();
public readonly onWillExecuteCommand: Event = this._onWillExecuteCommand.event;
constructor(instantiationService: IInstantiationService) {
diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts
index e4b771b30d1..8224e78e7f8 100644
--- a/src/vs/monaco.d.ts
+++ b/src/vs/monaco.d.ts
@@ -2787,6 +2787,11 @@ declare namespace monaco.editor {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
+ /**
+ * FastScrolling mulitplier speed when pressing `Alt`
+ * Defaults to 5.
+ */
+ fastScrollSensitivity?: number;
/**
* The modifier to be used to add multiple cursors with the mouse.
* Defaults to 'alt'
@@ -3149,6 +3154,7 @@ declare namespace monaco.editor {
readonly verticalScrollbarSize: number;
readonly verticalSliderSize: number;
readonly mouseWheelScrollSensitivity: number;
+ readonly fastScrollSensitivity: number;
}
export interface InternalEditorMinimapOptions {
diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts
index e34e8728d3e..38ba6e62460 100644
--- a/src/vs/platform/backup/electron-main/backupMainService.ts
+++ b/src/vs/platform/backup/electron-main/backupMainService.ts
@@ -7,7 +7,7 @@ import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import * as platform from 'vs/base/common/platform';
-import * as extfs from 'vs/base/node/extfs';
+import { writeFileAndFlushSync, readdirSync, delSync } from 'vs/base/node/extfs';
import * as arrays from 'vs/base/common/arrays';
import { IBackupMainService, IBackupWorkspacesFormat, IEmptyWindowBackupInfo } from 'vs/platform/backup/common/backup';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -23,14 +23,14 @@ import { Schemas } from 'vs/base/common/network';
export class BackupMainService implements IBackupMainService {
- public _serviceBrand: any;
+ _serviceBrand: any;
protected backupHome: string;
protected workspacesJsonPath: string;
- protected rootWorkspaces: IWorkspaceIdentifier[];
- protected folderWorkspaces: URI[];
- protected emptyWorkspaces: IEmptyWindowBackupInfo[];
+ private rootWorkspaces: IWorkspaceIdentifier[];
+ private folderWorkspaces: URI[];
+ private emptyWorkspaces: IEmptyWindowBackupInfo[];
constructor(
@IEnvironmentService environmentService: IEnvironmentService,
@@ -43,7 +43,7 @@ export class BackupMainService implements IBackupMainService {
this.loadSync();
}
- public getWorkspaceBackups(): IWorkspaceIdentifier[] {
+ getWorkspaceBackups(): IWorkspaceIdentifier[] {
if (this.isHotExitOnExitAndWindowClose()) {
// Only non-folder windows are restored on main process launch when
// hot exit is configured as onExitAndWindowClose.
@@ -53,16 +53,17 @@ export class BackupMainService implements IBackupMainService {
return this.rootWorkspaces.slice(0); // return a copy
}
- public getFolderBackupPaths(): URI[] {
+ getFolderBackupPaths(): URI[] {
if (this.isHotExitOnExitAndWindowClose()) {
// Only non-folder windows are restored on main process launch when
// hot exit is configured as onExitAndWindowClose.
return [];
}
+
return this.folderWorkspaces.slice(0); // return a copy
}
- public isHotExitEnabled(): boolean {
+ isHotExitEnabled(): boolean {
return this.getHotExitConfig() !== HotExitConfiguration.OFF;
}
@@ -76,11 +77,11 @@ export class BackupMainService implements IBackupMainService {
return (config && config.files && config.files.hotExit) || HotExitConfiguration.ON_EXIT;
}
- public getEmptyWindowBackupPaths(): IEmptyWindowBackupInfo[] {
+ getEmptyWindowBackupPaths(): IEmptyWindowBackupInfo[] {
return this.emptyWorkspaces.slice(0); // return a copy
}
- public registerWorkspaceBackupSync(workspace: IWorkspaceIdentifier, migrateFrom?: string): string {
+ registerWorkspaceBackupSync(workspace: IWorkspaceIdentifier, migrateFrom?: string): string {
if (!this.rootWorkspaces.some(w => w.id === workspace.id)) {
this.rootWorkspaces.push(workspace);
this.saveSync();
@@ -112,7 +113,7 @@ export class BackupMainService implements IBackupMainService {
}
}
- public unregisterWorkspaceBackupSync(workspace: IWorkspaceIdentifier): void {
+ unregisterWorkspaceBackupSync(workspace: IWorkspaceIdentifier): void {
let index = arrays.firstIndex(this.rootWorkspaces, w => w.id === workspace.id);
if (index !== -1) {
this.rootWorkspaces.splice(index, 1);
@@ -120,15 +121,16 @@ export class BackupMainService implements IBackupMainService {
}
}
- public registerFolderBackupSync(folderUri: URI): string {
+ registerFolderBackupSync(folderUri: URI): string {
if (!this.folderWorkspaces.some(uri => areResourcesEquals(folderUri, uri))) {
this.folderWorkspaces.push(folderUri);
this.saveSync();
}
+
return this.getBackupPath(this.getFolderHash(folderUri));
}
- public unregisterFolderBackupSync(folderUri: URI): void {
+ unregisterFolderBackupSync(folderUri: URI): void {
let index = arrays.firstIndex(this.folderWorkspaces, uri => areResourcesEquals(folderUri, uri));
if (index !== -1) {
this.folderWorkspaces.splice(index, 1);
@@ -136,22 +138,24 @@ export class BackupMainService implements IBackupMainService {
}
}
- public registerEmptyWindowBackupSync(backupInfo: IEmptyWindowBackupInfo): string {
-
+ registerEmptyWindowBackupSync(backupInfo: IEmptyWindowBackupInfo): string {
let backupFolder = backupInfo.backupFolder;
let remoteAuthority = backupInfo.remoteAuthority;
+
// Generate a new folder if this is a new empty workspace
if (!backupFolder) {
backupFolder = this.getRandomEmptyWindowId();
}
+
if (!this.emptyWorkspaces.some(w => isEqual(w.backupFolder, backupFolder, !platform.isLinux))) {
this.emptyWorkspaces.push({ backupFolder, remoteAuthority });
this.saveSync();
}
+
return this.getBackupPath(backupFolder);
}
- public unregisterEmptyWindowBackupSync(backupFolder: string): void {
+ unregisterEmptyWindowBackupSync(backupFolder: string): void {
let index = arrays.firstIndex(this.emptyWorkspaces, w => isEqual(w.backupFolder, backupFolder, !platform.isLinux));
if (index !== -1) {
this.emptyWorkspaces.splice(index, 1);
@@ -160,7 +164,6 @@ export class BackupMainService implements IBackupMainService {
}
protected loadSync(): void {
-
let backups: IBackupWorkspacesFormat;
try {
backups = JSON.parse(fs.readFileSync(this.workspacesJsonPath, 'utf8').toString()); // invalid JSON or permission issue can happen here
@@ -202,11 +205,11 @@ export class BackupMainService implements IBackupMainService {
} catch (e) {
// ignore URI parsing exceptions
}
+
this.folderWorkspaces = this.validateFolders(workspaceFolders);
// save again in case some workspaces or folders have been removed
this.saveSync();
-
}
private getBackupPath(oldFolderHash: string): string {
@@ -246,6 +249,7 @@ export class BackupMainService implements IBackupMainService {
}
}
}
+
return result;
}
@@ -256,7 +260,6 @@ export class BackupMainService implements IBackupMainService {
const result: URI[] = [];
const seen: { [id: string]: boolean } = Object.create(null);
-
for (let folderURI of folderWorkspaces) {
const key = getComparisonKey(folderURI);
if (!seen[key]) {
@@ -281,6 +284,7 @@ export class BackupMainService implements IBackupMainService {
return result;
}
+
private validateEmptyWorkspaces(emptyWorkspaces: IEmptyWindowBackupInfo[]): IEmptyWindowBackupInfo[] {
if (!Array.isArray(emptyWorkspaces)) {
return [];
@@ -314,7 +318,7 @@ export class BackupMainService implements IBackupMainService {
private deleteStaleBackup(backupPath: string) {
try {
if (fs.existsSync(backupPath)) {
- extfs.delSync(backupPath);
+ delSync(backupPath);
}
} catch (ex) {
this.logService.error(`Backup: Could not delete stale backup: ${ex.toString()}`);
@@ -344,14 +348,14 @@ export class BackupMainService implements IBackupMainService {
private hasBackupsSync(backupPath: string): boolean {
try {
- const backupSchemas = extfs.readdirSync(backupPath);
+ const backupSchemas = readdirSync(backupPath);
if (backupSchemas.length === 0) {
return false; // empty backups
}
return backupSchemas.some(backupSchema => {
try {
- return extfs.readdirSync(path.join(backupPath, backupSchema)).length > 0;
+ return readdirSync(path.join(backupPath, backupSchema)).length > 0;
} catch (error) {
return false; // invalid folder
}
@@ -363,17 +367,14 @@ export class BackupMainService implements IBackupMainService {
private saveSync(): void {
try {
- // The user data directory must exist so only the Backup directory needs to be checked.
- if (!fs.existsSync(this.backupHome)) {
- fs.mkdirSync(this.backupHome);
- }
const backups: IBackupWorkspacesFormat = {
rootWorkspaces: this.rootWorkspaces,
folderURIWorkspaces: this.folderWorkspaces.map(f => f.toString()),
emptyWorkspaceInfos: this.emptyWorkspaces,
emptyWorkspaces: this.emptyWorkspaces.map(info => info.backupFolder)
};
- extfs.writeFileAndFlushSync(this.workspacesJsonPath, JSON.stringify(backups));
+
+ writeFileAndFlushSync(this.workspacesJsonPath, JSON.stringify(backups));
} catch (ex) {
this.logService.error(`Backup: Could not save workspaces.json: ${ex.toString()}`);
}
@@ -384,14 +385,15 @@ export class BackupMainService implements IBackupMainService {
}
protected getFolderHash(folderUri: URI): string {
- let key;
+ let key: string;
+
if (folderUri.scheme === Schemas.file) {
// for backward compatibility, use the fspath as key
key = platform.isLinux ? folderUri.fsPath : folderUri.fsPath.toLowerCase();
-
} else {
key = hasToIgnoreCase(folderUri) ? folderUri.toString().toLowerCase() : folderUri.toString();
}
+
return crypto.createHash('md5').update(key).digest('hex');
}
diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts
index ce8d19d2831..7921caa38c0 100644
--- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts
+++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts
@@ -109,12 +109,13 @@ suite('BackupMainService', () => {
let configService: TestConfigurationService;
setup(() => {
- configService = new TestConfigurationService();
- service = new TestBackupMainService(backupHome, backupWorkspacesPath, configService);
// Delete any existing backups completely and then re-create it.
return pfs.del(backupHome, os.tmpdir()).then(() => {
return pfs.mkdirp(backupHome);
+ }).then(() => {
+ configService = new TestConfigurationService();
+ service = new TestBackupMainService(backupHome, backupWorkspacesPath, configService);
});
});
diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts
index a22359e8cb4..4cea7236d0d 100644
--- a/src/vs/platform/configuration/common/configurationRegistry.ts
+++ b/src/vs/platform/configuration/common/configurationRegistry.ts
@@ -10,6 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import * as types from 'vs/base/common/types';
import * as strings from 'vs/base/common/strings';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
+import { CanonicalExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export const Extensions = {
Configuration: 'base.contributions.configuration'
@@ -93,7 +94,7 @@ export interface IConfigurationNode {
}
export interface IDefaultConfigurationExtension {
- id: string;
+ id: CanonicalExtensionIdentifier;
name: string;
defaults: { [key: string]: {} };
}
@@ -115,7 +116,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
private overrideIdentifiers: string[] = [];
private overridePropertyPattern: string;
- private readonly _onDidSchemaChange: Emitter = new Emitter();
+ private readonly _onDidSchemaChange = new Emitter();
readonly onDidSchemaChange: Event = this._onDidSchemaChange.event;
private readonly _onDidRegisterConfiguration: Emitter = new Emitter();
diff --git a/src/vs/platform/dialogs/node/dialogService.ts b/src/vs/platform/dialogs/node/dialogService.ts
deleted file mode 100644
index cf04c7608e7..00000000000
--- a/src/vs/platform/dialogs/node/dialogService.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-import * as readline from 'readline';
-import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
-import Severity from 'vs/base/common/severity';
-import { localize } from 'vs/nls';
-import { canceled } from 'vs/base/common/errors';
-
-export class CommandLineDialogService implements IDialogService {
-
- _serviceBrand: any;
-
- show(severity: Severity, message: string, options: string[]): Promise {
- const promise = new Promise((c, e) => {
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: true
- });
- rl.prompt();
- rl.write(this.toQuestion(message, options));
-
- rl.prompt();
-
- rl.once('line', (answer) => {
- rl.close();
- c(this.toOption(answer, options));
- });
- rl.once('SIGINT', () => {
- rl.close();
- e(canceled());
- });
- });
- return promise;
- }
-
- private toQuestion(message: string, options: string[]): string {
- return options.reduce((previousValue: string, currentValue: string, currentIndex: number) => {
- return previousValue + currentValue + '(' + currentIndex + ')' + (currentIndex < options.length - 1 ? ' | ' : '\n');
- }, message + ' ');
- }
-
- private toOption(answer: string, options: string[]): number {
- const value = parseInt(answer);
- if (!isNaN(value)) {
- return value;
- }
- answer = answer.toLocaleLowerCase();
- for (let i = 0; i < options.length; i++) {
- if (options[i].toLocaleLowerCase() === answer) {
- return i;
- }
- }
- return -1;
- }
-
- confirm(confirmation: IConfirmation): Promise {
- return this.show(Severity.Info, confirmation.message, [confirmation.primaryButton || localize('ok', "Ok"), confirmation.secondaryButton || localize('cancel', "Cancel")]).then(index => {
- return {
- confirmed: index === 0
- } as IConfirmationResult;
- });
- }
-}
diff --git a/src/vs/platform/extensionManagement/test/electron-browser/extensionEnablementService.test.ts b/src/vs/platform/extensionManagement/test/electron-browser/extensionEnablementService.test.ts
index 5fa1d7cbb21..b898a8f1350 100644
--- a/src/vs/platform/extensionManagement/test/electron-browser/extensionEnablementService.test.ts
+++ b/src/vs/platform/extensionManagement/test/electron-browser/extensionEnablementService.test.ts
@@ -45,8 +45,8 @@ suite('ExtensionEnablementService Test', () => {
let instantiationService: TestInstantiationService;
let testObject: IExtensionEnablementService;
- const didUninstallEvent: Emitter = new Emitter();
- const didInstallEvent: Emitter = new Emitter();
+ const didUninstallEvent = new Emitter();
+ const didInstallEvent = new Emitter();
setup(() => {
instantiationService = new TestInstantiationService();
diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts
index 25998a367b2..101110e9403 100644
--- a/src/vs/platform/extensions/common/extensions.ts
+++ b/src/vs/platform/extensions/common/extensions.ts
@@ -6,6 +6,7 @@
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
+import * as strings from 'vs/base/common/strings';
export const MANIFEST_CACHE_FOLDER = 'CachedExtensions';
export const USER_MANIFEST_CACHE_FILE = 'user';
@@ -31,3 +32,58 @@ export function isUIExtension(manifest: IExtensionManifest, configurationService
default: return uiExtensions.has(extensionId) || !manifest.main;
}
}
+
+/**
+ * **!Do not construct directly!**
+ *
+ * **!Only static methods because it gets serialized!**
+ *
+ * This represents the "canonical" version for an extension identifier. Extension ids
+ * have to be case-insensitive (due to the marketplace), but we must ensure case
+ * preservation because the extension API is already public at this time.
+ *
+ * For example, given an extension with the publisher `"Hello"` and the name `"World"`,
+ * its canonical extension identifier is `"Hello.World"`. This extension could be
+ * referenced in some other extension's dependencies using the string `"hello.world"`.
+ *
+ * To make matters more complicated, an extension can optionally have an UUID. When two
+ * extensions have the same UUID, they are considered equal even if their identifier is different.
+ */
+export class CanonicalExtensionIdentifier {
+ public readonly value: string;
+ private readonly _lower: string;
+
+ constructor(value: string) {
+ this.value = value;
+ this._lower = value.toLowerCase();
+ }
+
+ public static equals(a: CanonicalExtensionIdentifier | string | null | undefined, b: CanonicalExtensionIdentifier | string | null | undefined) {
+ if (typeof a === 'undefined' || a === null) {
+ return (typeof b === 'undefined' || b === null);
+ }
+ if (typeof b === 'undefined' || b === null) {
+ return false;
+ }
+ if (typeof a === 'string' || typeof b === 'string') {
+ // At least one of the arguments is an extension id in string form,
+ // so we have to use the string comparison which ignores case.
+ let aValue = (typeof a === 'string' ? a : a.value);
+ let bValue = (typeof b === 'string' ? b : b.value);
+ return strings.equalsIgnoreCase(aValue, bValue);
+ }
+
+ // Now we know both arguments are CanonicalExtensionIdentifier
+ return (a._lower === b._lower);
+ }
+
+ /**
+ * Gives the value by which to index (for equality).
+ */
+ public static toKey(id: CanonicalExtensionIdentifier | string): string {
+ if (typeof id === 'string') {
+ return id.toLowerCase();
+ }
+ return id._lower;
+ }
+}
diff --git a/src/vs/platform/history/electron-main/historyMainService.ts b/src/vs/platform/history/electron-main/historyMainService.ts
index 88e7c2e5b2a..ac90272ec41 100644
--- a/src/vs/platform/history/electron-main/historyMainService.ts
+++ b/src/vs/platform/history/electron-main/historyMainService.ts
@@ -180,7 +180,6 @@ export class HistoryMainService implements IHistoryMainService {
// out of sync quickly over time. the attempted fix is to always set the list fresh
// from our MRU history data. So we clear the documents first and then set the documents
// again.
-
app.clearRecentDocuments();
const mru = this.getRecentlyOpened();
@@ -257,6 +256,7 @@ export class HistoryMainService implements IHistoryMainService {
if (workspaceOrFile instanceof URI) {
return getComparisonKey(workspaceOrFile);
}
+
return workspaceOrFile.id;
}
@@ -286,6 +286,7 @@ export class HistoryMainService implements IHistoryMainService {
}
}
}
+
if (Array.isArray(storedRecents.files2)) {
for (const file of storedRecents.files2) {
if (typeof file === 'string') {
@@ -300,11 +301,13 @@ export class HistoryMainService implements IHistoryMainService {
}
}
}
+
return result;
}
private saveRecentlyOpened(recent: IRecentlyOpened): void {
const serialized: ISerializedRecentlyOpened = { workspaces2: [], files2: [] };
+
for (const workspace of recent.workspaces) {
if (isSingleFolderWorkspaceIdentifier(workspace)) {
serialized.workspaces2.push(workspace.toString());
@@ -312,9 +315,11 @@ export class HistoryMainService implements IHistoryMainService {
serialized.workspaces2.push(workspace);
}
}
+
for (const file of recent.files) {
serialized.files2.push(file.toString());
}
+
this.stateService.setItem(HistoryMainService.recentlyOpenedStorageKey, serialized);
}
diff --git a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts
index bc631b93ef7..2f173cd9838 100644
--- a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts
+++ b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts
@@ -52,7 +52,7 @@ class JSONContributionRegistry implements IJSONContributionRegistry {
private schemasById: { [id: string]: IJSONSchema };
- private readonly _onDidChangeSchema: Emitter = new Emitter();
+ private readonly _onDidChangeSchema = new Emitter();
readonly onDidChangeSchema: Event = this._onDidChangeSchema.event;
constructor() {
diff --git a/src/vs/platform/keybinding/common/abstractKeybindingService.ts b/src/vs/platform/keybinding/common/abstractKeybindingService.ts
index 7e6f07aff23..da4d3af573c 100644
--- a/src/vs/platform/keybinding/common/abstractKeybindingService.ts
+++ b/src/vs/platform/keybinding/common/abstractKeybindingService.ts
@@ -156,10 +156,20 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
this._currentChord = null;
}
+ public dispatchByUserSettingsLabel(userSettingsLabel: string, target: IContextKeyServiceTarget): void {
+ const keybindings = this.resolveUserBinding(userSettingsLabel);
+ if (keybindings.length >= 1) {
+ this._doDispatch(keybindings[0], target);
+ }
+ }
+
protected _dispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {
+ return this._doDispatch(this.resolveKeyboardEvent(e), target);
+ }
+
+ private _doDispatch(keybinding: ResolvedKeybinding, target: IContextKeyServiceTarget): boolean {
let shouldPreventDefault = false;
- const keybinding = this.resolveKeyboardEvent(e);
if (keybinding.isChord()) {
console.warn('Unexpected keyboard event mapped to a chord');
return false;
diff --git a/src/vs/platform/keybinding/common/keybinding.ts b/src/vs/platform/keybinding/common/keybinding.ts
index 762362bd8cd..0cef819a75c 100644
--- a/src/vs/platform/keybinding/common/keybinding.ts
+++ b/src/vs/platform/keybinding/common/keybinding.ts
@@ -62,6 +62,8 @@ export interface IKeybindingService {
*/
softDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null;
+ dispatchByUserSettingsLabel(userSettingsLabel: string, target: IContextKeyServiceTarget): void;
+
/**
* Look up keybindings for a command.
* Use `lookupKeybinding` if you are interested in the preferred keybinding.
diff --git a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts
index 42213cc40a7..5cf1babe59b 100644
--- a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts
+++ b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts
@@ -120,6 +120,10 @@ export class MockKeybindingService implements IKeybindingService {
return null;
}
+ public dispatchByUserSettingsLabel(userSettingsLabel: string, target: IContextKeyServiceTarget): void {
+
+ }
+
public dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {
return false;
}
diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts
index 9932cf6a0a3..b9d7146387e 100644
--- a/src/vs/platform/list/browser/listService.ts
+++ b/src/vs/platform/list/browser/listService.ts
@@ -505,7 +505,7 @@ export interface IResourceResultsNavigationOptions {
export class TreeResourceNavigator extends Disposable {
- private readonly _openResource: Emitter = new Emitter();
+ private readonly _openResource = new Emitter();
readonly openResource: Event = this._openResource.event;
constructor(private tree: WorkbenchTree, private options?: IResourceResultsNavigationOptions) {
diff --git a/src/vs/platform/menubar/common/menubar.ts b/src/vs/platform/menubar/common/menubar.ts
index c88dab47842..84ceaf14ec2 100644
--- a/src/vs/platform/menubar/common/menubar.ts
+++ b/src/vs/platform/menubar/common/menubar.ts
@@ -25,6 +25,7 @@ export interface IMenubarMenu {
export interface IMenubarKeybinding {
label: string;
+ userSettingsLabel: string;
isNative?: boolean; // Assumed true if missing
}
diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts
index 7481c400fc7..43c65fcdb05 100644
--- a/src/vs/platform/menubar/electron-main/menubar.ts
+++ b/src/vs/platform/menubar/electron-main/menubar.ts
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import { isMacintosh, language } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { app, shell, Menu, MenuItem, BrowserWindow } from 'electron';
-import { OpenContext, IRunActionInWindowRequest, getTitleBarStyle } from 'vs/platform/windows/common/windows';
+import { OpenContext, IRunActionInWindowRequest, getTitleBarStyle, IRunKeybindingInWindowRequest } from 'vs/platform/windows/common/windows';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IUpdateService, StateType } from 'vs/platform/update/common/update';
@@ -29,6 +29,15 @@ interface IMenuItemClickHandler {
inNoWindow: () => void;
}
+type IMenuItemInvocation = (
+ { type: 'commandId'; commandId: string; }
+ | { type: 'keybinding'; userSettingsLabel: string; }
+);
+
+interface IMenuItemWithKeybinding {
+ userSettingsLabel?: string;
+}
+
export class Menubar {
private static readonly lastKnownMenubarStorageKey = 'lastKnownMenubarData';
@@ -84,10 +93,6 @@ export class Menubar {
}
private restoreCachedMenubarData() {
- // TODO@sbatten remove this at some point down the road
- const outdatedKeys = ['lastKnownAdditionalKeybindings', 'lastKnownKeybindings', 'lastKnownMenubar'];
- outdatedKeys.forEach(key => this.stateService.removeItem(key));
-
const menubarData = this.stateService.getItem(Menubar.lastKnownMenubarStorageKey);
if (menubarData) {
if (menubarData.menus) {
@@ -573,17 +578,49 @@ export class Menubar {
}
}
+ private static _menuItemIsTriggeredViaKeybinding(event: Electron.Event, userSettingsLabel: string): boolean {
+ // The event coming in from Electron will inform us only about the modifier keys pressed.
+ // The strategy here is to check if the modifier keys match those of the keybinding,
+ // since it is highly unlikely to use modifier keys when clicking with the mouse
+ if (!userSettingsLabel) {
+ // There is no keybinding
+ return false;
+ }
+
+ let ctrlRequired = /ctrl/.test(userSettingsLabel);
+ let shiftRequired = /shift/.test(userSettingsLabel);
+ let altRequired = /alt/.test(userSettingsLabel);
+ let metaRequired = /cmd/.test(userSettingsLabel) || /super/.test(userSettingsLabel);
+
+ if (!ctrlRequired && !shiftRequired && !altRequired && !metaRequired) {
+ // This keybinding does not use any modifier keys, so we cannot use this heuristic
+ return false;
+ }
+
+ return (
+ ctrlRequired === event.ctrlKey
+ && shiftRequired === event.shiftKey
+ && altRequired === event.altKey
+ && metaRequired === event.metaKey
+ );
+ }
+
private createMenuItem(label: string, commandId: string | string[], enabled?: boolean, checked?: boolean): Electron.MenuItem;
private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): Electron.MenuItem;
private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): Electron.MenuItem {
const label = this.mnemonicLabel(arg1);
- const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: Electron.MenuItem, win: Electron.BrowserWindow, event: Electron.Event) => {
+ const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: Electron.MenuItem & IMenuItemWithKeybinding, win: Electron.BrowserWindow, event: Electron.Event) => {
+ const userSettingsLabel = menuItem.userSettingsLabel;
let commandId = arg2;
if (Array.isArray(arg2)) {
commandId = this.isOptionClick(event) ? arg2[1] : arg2[0]; // support alternative action if we got multiple action Ids and the option key was pressed while invoking
}
- this.runActionInRenderer(commandId);
+ if (userSettingsLabel && Menubar._menuItemIsTriggeredViaKeybinding(event, userSettingsLabel)) {
+ this.runActionInRenderer({ type: 'keybinding', userSettingsLabel });
+ } else {
+ this.runActionInRenderer({ type: 'commandId', commandId });
+ }
};
const enabled = typeof arg3 === 'boolean' ? arg3 : this.windowsMainService.getWindowCount() > 0;
const checked = typeof arg4 === 'boolean' ? arg4 : false;
@@ -656,7 +693,7 @@ export class Menubar {
};
}
- private runActionInRenderer(id: string): void {
+ private runActionInRenderer(invocation: IMenuItemInvocation): void {
// We make sure to not run actions when the window has no focus, this helps
// for https://github.com/Microsoft/vscode/issues/25907 and specifically for
// https://github.com/Microsoft/vscode/issues/11928
@@ -671,18 +708,21 @@ export class Menubar {
}
if (activeWindow) {
- if (!activeWindow.isReady && isMacintosh && id === 'workbench.action.toggleDevTools' && !this.environmentService.isBuilt) {
- // prevent this action from running twice on macOS (https://github.com/Microsoft/vscode/issues/62719)
- // we already register a keybinding in bootstrap-window.js for opening developer tools in case something
- // goes wrong and that keybinding is only removed when the application has loaded (= window ready).
- return;
+ if (invocation.type === 'commandId') {
+ if (!activeWindow.isReady && isMacintosh && invocation.commandId === 'workbench.action.toggleDevTools' && !this.environmentService.isBuilt) {
+ // prevent this action from running twice on macOS (https://github.com/Microsoft/vscode/issues/62719)
+ // we already register a keybinding in bootstrap-window.js for opening developer tools in case something
+ // goes wrong and that keybinding is only removed when the application has loaded (= window ready).
+ return;
+ }
+ this.windowsMainService.sendToFocused('vscode:runAction', { id: invocation.commandId, from: 'menu' } as IRunActionInWindowRequest);
+ } else {
+ this.windowsMainService.sendToFocused('vscode:runKeybinding', { userSettingsLabel: invocation.userSettingsLabel } as IRunKeybindingInWindowRequest);
}
-
- this.windowsMainService.sendToFocused('vscode:runAction', { id, from: 'menu' } as IRunActionInWindowRequest);
}
}
- private withKeybinding(commandId: string | undefined, options: Electron.MenuItemConstructorOptions): Electron.MenuItemConstructorOptions {
+ private withKeybinding(commandId: string | undefined, options: Electron.MenuItemConstructorOptions & IMenuItemWithKeybinding): Electron.MenuItemConstructorOptions {
const binding = typeof commandId === 'string' ? this.keybindings[commandId] : undefined;
// Apply binding if there is one
@@ -691,6 +731,7 @@ export class Menubar {
// if the binding is native, we can just apply it
if (binding.isNative !== false) {
options.accelerator = binding.label;
+ options.userSettingsLabel = binding.userSettingsLabel;
}
// the keybinding is not native so we cannot show it as part of the accelerator of
diff --git a/src/vs/platform/remote/common/remoteAuthorityResolver.ts b/src/vs/platform/remote/common/remoteAuthorityResolver.ts
index 51628f97ee5..d028e37cce8 100644
--- a/src/vs/platform/remote/common/remoteAuthorityResolver.ts
+++ b/src/vs/platform/remote/common/remoteAuthorityResolver.ts
@@ -12,6 +12,8 @@ export interface ResolvedAuthority {
readonly host: string;
readonly port: number;
readonly syncExtensions: boolean;
+ readonly debugListenPort?: number;
+ readonly debugConnectPort?: number;
}
export interface IRemoteAuthorityResolverService {
diff --git a/src/vs/platform/remote/node/remoteAgentConnection.ts b/src/vs/platform/remote/node/remoteAgentConnection.ts
index ddcb7177b4d..2ab02017c16 100644
--- a/src/vs/platform/remote/node/remoteAgentConnection.ts
+++ b/src/vs/platform/remote/node/remoteAgentConnection.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { Client, Protocol } from 'vs/base/parts/ipc/node/ipc.net';
+import { Client, BufferedProtocol } from 'vs/base/parts/ipc/node/ipc.net';
import { IExtensionHostDebugParams } from 'vs/platform/environment/common/environment';
export interface RemoteAgentConnectionContext {
@@ -11,15 +11,19 @@ export interface RemoteAgentConnectionContext {
clientId: string;
}
-export function connectRemoteAgentManagement(remoteAuthority: string, host: string, port: number, clientId: string): Promise> {
+export function connectRemoteAgentManagement(remoteAuthority: string, host: string, port: number, clientId: string, isBuilt: boolean): Promise> {
throw new Error(`Not implemented`);
}
export interface IExtensionHostConnectionResult {
- protocol: Protocol;
+ protocol: BufferedProtocol;
debugPort?: number;
}
-export function connectRemoteAgentExtensionHost(host: string, port: number, debugArguments: IExtensionHostDebugParams): Promise {
+export interface IRemoteExtensionHostDebugParams extends IExtensionHostDebugParams {
+ updatePort?: boolean;
+}
+
+export function connectRemoteAgentExtensionHost(host: string, port: number, debugArguments: IRemoteExtensionHostDebugParams, isBuilt: boolean): Promise {
throw new Error(`Not implemented`);
}
diff --git a/src/vs/platform/state/node/stateService.ts b/src/vs/platform/state/node/stateService.ts
index bc513bbdbfe..c4b5bc9bad8 100644
--- a/src/vs/platform/state/node/stateService.ts
+++ b/src/vs/platform/state/node/stateService.ts
@@ -10,18 +10,52 @@ import { writeFileAndFlushSync } from 'vs/base/node/extfs';
import { isUndefined, isUndefinedOrNull } from 'vs/base/common/types';
import { IStateService } from 'vs/platform/state/common/state';
import { ILogService } from 'vs/platform/log/common/log';
+import { readFile } from 'vs/base/node/pfs';
export class FileStorage {
- private _lazyDatabase: object | null = null;
+ private _database: object | null = null;
+ private lastFlushedSerializedDatabase: string | null = null;
- constructor(private dbPath: string, private onError: (error) => void) { }
+ constructor(private dbPath: string, private onError: (error: Error) => void) { }
private get database(): object {
- if (!this._lazyDatabase) {
- this._lazyDatabase = this.loadSync();
+ if (!this._database) {
+ this._database = this.loadSync();
+ }
+
+ return this._database;
+ }
+
+ init(): Promise {
+ return readFile(this.dbPath).then(contents => {
+ try {
+ this.lastFlushedSerializedDatabase = contents.toString();
+ this._database = JSON.parse(this.lastFlushedSerializedDatabase);
+ } catch (error) {
+ this._database = {};
+ }
+ }, error => {
+ if (error.code !== 'ENOENT') {
+ this.onError(error);
+ }
+
+ this._database = {};
+ });
+ }
+
+ private loadSync(): object {
+ try {
+ this.lastFlushedSerializedDatabase = fs.readFileSync(this.dbPath).toString();
+
+ return JSON.parse(this.lastFlushedSerializedDatabase);
+ } catch (error) {
+ if (error.code !== 'ENOENT') {
+ this.onError(error);
+ }
+
+ return {};
}
- return this._lazyDatabase;
}
getItem(key: string, defaultValue: T): T;
@@ -36,6 +70,7 @@ export class FileStorage {
}
setItem(key: string, data: any): void {
+
// Remove an item when it is undefined or null
if (isUndefinedOrNull(data)) {
return this.removeItem(key);
@@ -53,6 +88,7 @@ export class FileStorage {
}
removeItem(key: string): void {
+
// Only update if the key is actually present (not undefined)
if (!isUndefined(this.database[key])) {
this.database[key] = void 0;
@@ -60,21 +96,15 @@ export class FileStorage {
}
}
- private loadSync(): object {
- try {
- return JSON.parse(fs.readFileSync(this.dbPath).toString()); // invalid JSON or permission issue can happen here
- } catch (error) {
- if (error && error.code !== 'ENOENT') {
- this.onError(error);
- }
-
- return {};
- }
- }
-
private saveSync(): void {
+ const serializedDatabase = JSON.stringify(this.database, null, 4);
+ if (serializedDatabase === this.lastFlushedSerializedDatabase) {
+ return; // return early if the database has not changed
+ }
+
try {
- writeFileAndFlushSync(this.dbPath, JSON.stringify(this.database, null, 4)); // permission issue can happen here
+ writeFileAndFlushSync(this.dbPath, serializedDatabase); // permission issue can happen here
+ this.lastFlushedSerializedDatabase = serializedDatabase;
} catch (error) {
this.onError(error);
}
@@ -85,10 +115,19 @@ export class StateService implements IStateService {
_serviceBrand: any;
+ private static STATE_FILE = 'storage.json';
+
private fileStorage: FileStorage;
- constructor(@IEnvironmentService environmentService: IEnvironmentService, @ILogService logService: ILogService) {
- this.fileStorage = new FileStorage(path.join(environmentService.userDataPath, 'storage.json'), error => logService.error(error));
+ constructor(
+ @IEnvironmentService environmentService: IEnvironmentService,
+ @ILogService logService: ILogService
+ ) {
+ this.fileStorage = new FileStorage(path.join(environmentService.userDataPath, StateService.STATE_FILE), error => logService.error(error));
+ }
+
+ init(): Promise {
+ return this.fileStorage.init();
}
getItem(key: string, defaultValue: T): T;
diff --git a/src/vs/platform/statusbar/common/statusbar.ts b/src/vs/platform/statusbar/common/statusbar.ts
index a14dc163806..f2d4097c2b2 100644
--- a/src/vs/platform/statusbar/common/statusbar.ts
+++ b/src/vs/platform/statusbar/common/statusbar.ts
@@ -6,6 +6,7 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
+import { CanonicalExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export const IStatusbarService = createDecorator('statusbarService');
@@ -48,7 +49,7 @@ export interface IStatusbarEntry {
/**
* An optional extension ID if this entry is provided from an extension.
*/
- readonly extensionId?: string;
+ readonly extensionId?: CanonicalExtensionIdentifier;
/**
* Wether to show a beak above the status bar entry.
diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts
index ebd65fc8513..e9fc3f9586f 100644
--- a/src/vs/platform/storage/node/storageService.ts
+++ b/src/vs/platform/storage/node/storageService.ts
@@ -107,6 +107,11 @@ export class StorageService extends Disposable implements IStorageService {
return Promise.reject(error);
});
+ }).then(void 0, error => {
+ onUnexpectedError(error);
+
+ // Upon error, fallback to in-memory storage
+ return this.createWorkspaceStorage(SQLiteStorageDatabase.IN_MEMORY_PATH).init();
});
}
diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts
index 78a8bd74f86..86239c3480f 100644
--- a/src/vs/platform/theme/common/colorRegistry.ts
+++ b/src/vs/platform/theme/common/colorRegistry.ts
@@ -195,7 +195,7 @@ export const selectBorder = registerColor('dropdown.border', { dark: selectBackg
export const listFocusBackground = registerColor('list.focusBackground', { dark: '#062F4A', light: '#D6EBFF', hc: null }, nls.localize('listFocusBackground', "List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not."));
export const listFocusForeground = registerColor('list.focusForeground', { dark: null, light: null, hc: null }, nls.localize('listFocusForeground', "List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not."));
-export const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#094771', light: '#2477CE', hc: null }, nls.localize('listActiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not."));
+export const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#094771', light: '#0074E8', hc: null }, nls.localize('listActiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not."));
export const listActiveSelectionForeground = registerColor('list.activeSelectionForeground', { dark: Color.white, light: Color.white, hc: null }, nls.localize('listActiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not."));
export const listInactiveSelectionBackground = registerColor('list.inactiveSelectionBackground', { dark: '#37373D', light: '#E4E6F1', hc: null }, nls.localize('listInactiveSelectionBackground', "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not."));
export const listInactiveSelectionForeground = registerColor('list.inactiveSelectionForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionForeground', "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not."));
diff --git a/src/vs/platform/update/electron-main/updateService.snap.ts b/src/vs/platform/update/electron-main/updateService.snap.ts
index ed0cb25b057..c11676fed4b 100644
--- a/src/vs/platform/update/electron-main/updateService.snap.ts
+++ b/src/vs/platform/update/electron-main/updateService.snap.ts
@@ -14,6 +14,7 @@ import * as path from 'path';
import { realpath, watch } from 'fs';
import { spawn } from 'child_process';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
+import { stat } from 'vs/base/node/pfs';
abstract class AbstractUpdateService2 implements IUpdateService {
@@ -136,7 +137,11 @@ export class SnapUpdateService extends AbstractUpdateService2 {
_serviceBrand: any;
+ private snapUpdatePath: string;
+
constructor(
+ private snap: string,
+ private snapRevision: string,
@ILifecycleService lifecycleService: ILifecycleService,
@IEnvironmentService environmentService: IEnvironmentService,
@ILogService logService: ILogService,
@@ -144,10 +149,9 @@ export class SnapUpdateService extends AbstractUpdateService2 {
) {
super(lifecycleService, environmentService, logService);
- if (typeof process.env.SNAP === 'undefined') {
- throw new Error(`'SNAP' environment variable not set`);
- }
- const watcher = watch(path.dirname(process.env.SNAP));
+ this.snapUpdatePath = path.join(this.snap, `usr/share/${product.applicationName}/snapUpdate.sh`);
+
+ const watcher = watch(path.dirname(this.snap));
const onChange = Event.fromNodeEventEmitter(watcher, 'change', (_, fileName: string) => fileName);
const onCurrentChange = Event.filter(onChange, n => n === 'current');
const onDebouncedCurrentChange = Event.debounce(onCurrentChange, (_, e) => e, 2000);
@@ -164,7 +168,7 @@ export class SnapUpdateService extends AbstractUpdateService2 {
this.isUpdateAvailable().then(result => {
if (result) {
- this.setState(State.Ready({ version: 'something', productVersion: 'someting' }));
+ this.setState(State.Ready({ version: 'something', productVersion: 'something' }));
} else {
/* __GDPR__
"update:notAvailable" : {
@@ -191,26 +195,23 @@ export class SnapUpdateService extends AbstractUpdateService2 {
protected doQuitAndInstall(): void {
this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()');
- if (typeof process.env.SNAP === 'undefined') {
- return;
- }
-
// Allow 3 seconds for VS Code to close
- spawn('bash', ['-c', path.join(process.env.SNAP, `usr/share/${product.applicationName}/snapUpdate.sh`)], {
+ spawn('bash', ['-c', this.snapUpdatePath], {
detached: true,
stdio: ['ignore', 'ignore', 'ignore']
});
}
- private isUpdateAvailable(): Promise {
- return new Promise((c, e) => {
- realpath(`/snap/${product.applicationName}/current`, (err, resolvedCurrentSnapPath) => {
- if (err) { return e(err); }
+ private async isUpdateAvailable(): Promise {
+ try {
+ await stat(this.snapUpdatePath);
+ } catch (err) {
+ return false;
+ }
- const currentRevision = path.basename(resolvedCurrentSnapPath);
- c(process.env.SNAP_REVISION !== currentRevision);
- });
- });
+ const resolvedCurrentSnapPath = await new Promise((c, e) => realpath(`${path.dirname(this.snap)}/current`, (err, r) => err ? e(err) : c(r)));
+ const currentRevision = path.basename(resolvedCurrentSnapPath);
+ return this.snapRevision !== currentRevision;
}
isLatestVersion(): Promise {
diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts
index e6d5f0048b5..b68575d2b2c 100644
--- a/src/vs/platform/windows/common/windows.ts
+++ b/src/vs/platform/windows/common/windows.ts
@@ -409,6 +409,10 @@ export interface IRunActionInWindowRequest {
args?: any[];
}
+export interface IRunKeybindingInWindowRequest {
+ userSettingsLabel: string;
+}
+
export class ActiveWindowManager implements IDisposable {
private disposables: IDisposable[] = [];
diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts
index 430c42aca4d..945417405a4 100644
--- a/src/vs/vscode.d.ts
+++ b/src/vs/vscode.d.ts
@@ -1854,6 +1854,11 @@ declare module 'vscode' {
* * `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
* * `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
* * `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
+ *
+ * Note: a backslash (`\`) is not valid within a glob pattern. If you have an existing file
+ * path to match against, consider to use the [relative pattern](#RelativePattern) support
+ * that takes care of converting any backslash into slash. Otherwise, make sure to convert
+ * any backslash to slash when creating the glob pattern.
*/
export type GlobPattern = string | RelativePattern;
diff --git a/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts b/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts
index 299da54da22..7de2b9f8ff9 100644
--- a/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts
+++ b/src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts
@@ -30,6 +30,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { URI } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { CanonicalExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;
@@ -147,12 +148,12 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
containers.forEach(descriptor => {
const cssClass = `extensionViewlet-${descriptor.id}`;
const icon = resources.joinPath(extension.extensionLocation, descriptor.icon);
- this.registerCustomViewlet({ id: `workbench.view.extension.${descriptor.id}`, title: descriptor.title, icon }, order++, cssClass, extension.id);
+ this.registerCustomViewlet({ id: `workbench.view.extension.${descriptor.id}`, title: descriptor.title, icon }, order++, cssClass, extension.identifier);
});
return order;
}
- private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor2, order: number, cssClass: string, extensionId: string): void {
+ private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor2, order: number, cssClass: string, extensionId: CanonicalExtensionIdentifier): void {
const viewContainersRegistry = Registry.as