diff --git a/.travis.yml b/.travis.yml index 12d94a22d1b..1f28f9d55cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ addons: - libsecret-1-dev before_install: + - export GITHUB_TOKEN=$PUBLIC_GITHUB_TOKEN - git submodule update --init --recursive - git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm - source ./.nvm/nvm.sh diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 587e8ab262a..98c32784879 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -45,8 +45,8 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.19.7' }, - { name: 'ms-vscode.node-debug2', version: '1.19.3' } + { name: 'ms-vscode.node-debug', version: '1.20.0' }, + { name: 'ms-vscode.node-debug2', version: '1.19.4' } ]; const excludedExtensions = [ diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 84196a8b658..498080ea9f4 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -318,7 +318,7 @@ "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", "@emmetio/math-expression": "^0.1.1", "vscode-emmet-helper": "^1.1.19", - "vscode-languageserver-types": "^3.0.3", + "vscode-languageserver-types": "^3.5.0", "image-size": "^0.5.2", "vscode-nls": "2.0.2" } diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index 7d331f575b7..ad611574c05 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -23,6 +23,12 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi const isSyntaxMapped = mappedLanguages[document.languageId] ? true : false; let syntax = getEmmetMode((isSyntaxMapped ? mappedLanguages[document.languageId] : document.languageId), excludedLanguages); + if (!syntax + || emmetConfig['showExpandedAbbreviation'] === 'never' + || ((isSyntaxMapped || syntax === 'jsx') && emmetConfig['showExpandedAbbreviation'] !== 'always')) { + return; + } + const helper = getEmmetHelper(); const extractAbbreviationResults = helper.extractAbbreviation(document, position); if (!extractAbbreviationResults) { @@ -46,12 +52,6 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi } } - if (!syntax - || ((isSyntaxMapped || syntax === 'jsx') - && emmetConfig['showExpandedAbbreviation'] !== 'always')) { - return; - } - let noiseCheckPromise: Thenable = Promise.resolve(); // Fix for https://github.com/Microsoft/vscode/issues/32647 diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 8d8874a062d..697ec7fb017 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -2059,6 +2059,10 @@ vscode-languageserver-types@^3.0.3: version "3.3.0" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.3.0.tgz#8964dc7c2247536fbefd2d6836bf3febac80dd00" +vscode-languageserver-types@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374" + vscode-nls@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index e96d54d708e..4ee58c70fff 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -519,6 +519,7 @@ export class Repository implements Disposable { this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)"); this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.quickDiffProvider = this; + this._sourceControl.inputBox.lineWarningLength = 72; this.disposables.push(this._sourceControl); this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes")); diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index 15da42cf0a9..42e28260ce3 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -11,8 +11,8 @@ ], "main": "./out/javascriptMain", "dependencies": { - "jsonc-parser": "^0.3.1", - "request-light": "^0.2.0", + "jsonc-parser": "^1.0.0", + "request-light": "^0.2.1", "vscode-nls": "^2.0.2" }, "scripts": { diff --git a/extensions/javascript/yarn.lock b/extensions/javascript/yarn.lock index 889a7bad9ce..03e618404f4 100644 --- a/extensions/javascript/yarn.lock +++ b/extensions/javascript/yarn.lock @@ -36,19 +36,17 @@ https-proxy-agent@^0.3.5: debug "2" extend "3" -jsonc-parser@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-0.3.1.tgz#6ebf5c75224368d4b07ef4c26f9434e657472e95" - dependencies: - vscode-nls "^2.0.2" +jsonc-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272" ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -request-light@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.0.tgz#922497791c2e68528124dfb82354cf37e4bb2cfc" +request-light@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.1.tgz#986f5a82893e9d1ca6a896ebe6f46c51c6b4557f" dependencies: http-proxy-agent "^0.2.6" https-proxy-agent "^0.3.5" diff --git a/extensions/markdown/media/main.js b/extensions/markdown/media/main.js index ddf21afbbb9..4b5cf807476 100644 --- a/extensions/markdown/media/main.js +++ b/extensions/markdown/media/main.js @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - +// @ts-check 'use strict'; (function () { @@ -29,6 +29,13 @@ }; } + function postMessage(command, args) { + window.parent.postMessage({ + command: 'did-click-link', + data: `command:${command}?${encodeURIComponent(JSON.stringify(args))}` + }, 'file://'); + } + /** * Find the html elements that map to a specific target line in the editor. * @@ -196,14 +203,34 @@ const offset = event.pageY; const line = getEditorLineNumberForPageOffset(offset); if (!isNaN(line)) { - const args = [settings.source, line]; - window.parent.postMessage({ - command: "did-click-link", - data: `command:_markdown.didClick?${encodeURIComponent(JSON.stringify(args))}` - }, "file://"); + postMessage('_markdown.didClick', [settings.source, line]); } }); + document.addEventListener('click', event => { + if (!event) { + return; + } + + const baseElement = document.getElementsByTagName('base')[0]; + + /** @type {any} */ + let node = event.target; + while (node) { + if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) { + if (node.href.startsWith('file://')) { + const [path, fragment] = node.href.replace(/^file:\/\//i, '').split('#'); + postMessage('_markdown.openDocumentLink', { path, fragment }); + event.preventDefault(); + event.stopPropagation(); + break; + } + break; + } + node = node.parentNode; + } + }, true); + if (settings.scrollEditorWithPreview) { window.addEventListener('scroll', throttle(() => { if (scrollDisabled) { @@ -211,11 +238,7 @@ } else { const line = getEditorLineNumberForPageOffset(window.scrollY); if (!isNaN(line)) { - const args = [settings.source, line]; - window.parent.postMessage({ - command: 'did-click-link', - data: `command:_markdown.revealLine?${encodeURIComponent(JSON.stringify(args))}` - }, 'file://'); + postMessage('_markdown.revealLine', [settings.source, line]); } } }, 50)); diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index f26564acd10..038c3f1b5e3 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -311,8 +311,8 @@ "highlight.js": "9.5.0", "markdown-it": "^8.4.0", "markdown-it-named-headers": "0.0.4", - "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "2.0.2" + "vscode-extension-telemetry": "^0.0.8", + "vscode-nls": "^2.0.2" }, "devDependencies": { "@types/highlight.js": "9.1.10", diff --git a/extensions/markdown/src/commands.ts b/extensions/markdown/src/commands.ts index 0051c2fa0f8..af92114b50a 100644 --- a/extensions/markdown/src/commands.ts +++ b/extensions/markdown/src/commands.ts @@ -264,6 +264,16 @@ export class OpenDocumentLinkCommand implements Command { new vscode.Range(line, 0, line, 0), vscode.TextEditorRevealType.AtTop); } + + const lineNumberFragment = args.fragment.match(/^L(\d+)$/); + if (lineNumberFragment) { + const line = +lineNumberFragment[1] - 1; + if (!isNaN(line)) { + return editor.revealRange( + new vscode.Range(line, 0, line, 0), + vscode.TextEditorRevealType.AtTop); + } + } } }; diff --git a/extensions/markdown/src/markdownEngine.ts b/extensions/markdown/src/markdownEngine.ts index 4ed96316277..a4be37ed984 100644 --- a/extensions/markdown/src/markdownEngine.ts +++ b/extensions/markdown/src/markdownEngine.ts @@ -137,8 +137,9 @@ export class MarkdownEngine { md.normalizeLink = (link: string) => { try { let uri = vscode.Uri.parse(link); - if (!uri.scheme && uri.path && !uri.fragment) { + if (!uri.scheme && uri.path) { // Assume it must be a file + const fragment = uri.fragment; if (uri.path[0] === '/') { const root = vscode.workspace.getWorkspaceFolder(this.currentDocument); if (root) { @@ -147,6 +148,10 @@ export class MarkdownEngine { } else { uri = vscode.Uri.file(path.join(path.dirname(this.currentDocument.path), uri.path)); } + + if (fragment) { + uri = uri.with({ fragment }); + } return normalizeLink(uri.toString(true)); } } catch (e) { diff --git a/extensions/markdown/yarn.lock b/extensions/markdown/yarn.lock index 2b58fcb5d2f..4baed92f526 100644 --- a/extensions/markdown/yarn.lock +++ b/extensions/markdown/yarn.lock @@ -155,14 +155,14 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -vscode-extension-telemetry@0.0.8: +vscode-extension-telemetry@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0" dependencies: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@2.0.2: +vscode-nls@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" diff --git a/extensions/ms-vscode.node-debug/package-lock.json b/extensions/ms-vscode.node-debug/package-lock.json index 82260da1aa1..526e856f483 100644 --- a/extensions/ms-vscode.node-debug/package-lock.json +++ b/extensions/ms-vscode.node-debug/package-lock.json @@ -1,6 +1,6 @@ { "name": "node-debug", - "version": "1.19.2", + "version": "1.19.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -42,21 +42,21 @@ } }, "@types/mocha": { - "version": "2.2.42", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.42.tgz", - "integrity": "sha512-b6gVDoxEbAQGwbV7gSzeFw/hy3/eEAokztktdzl4bHvGgb9K5zW4mVQDlVYch2w31m8t/J7L2iqhQvz3r5edCQ==", + "version": "2.2.44", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", + "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==", "dev": true }, "@types/node": { - "version": "6.0.52", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.52.tgz", - "integrity": "sha1-GsOpm0IyD55GNILyWvTCNZRzqqY=", + "version": "7.0.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.43.tgz", + "integrity": "sha512-7scYwwfHNppXvH/9JzakbVxk0o0QUILVk1Lv64GRaxwPuGpnF1QBiwdvhDpLcymb8BpomQL3KYoWKq3wUdDMhQ==", "dev": true }, "@types/source-map": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.1.tgz", - "integrity": "sha512-/GVAjL1Y8puvZab63n8tsuBiYwZt1bApMdx58/msQ9ID5T05ov+wm/ZV1DvYC/DKKEygpTJViqQvkh5Rhrl4CA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.2.tgz", + "integrity": "sha512-++w4WmMbk3dS3UeHGzAG+xJOSz5Xqtjys/TBkqG3qp3SeWE7Wwezqe5eB7B51cxUyh4PW7bwVotpsLdBK0D8cw==", "dev": true }, "abbrev": { @@ -4755,9 +4755,9 @@ } }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.5.0.tgz", + "integrity": "sha512-v/jMDoK/qKptnTuC3YUNbIj8uUYvTCIHzVu9BHldKSWja48wusAtfjlcBlqnFrqClu3yf69ScDxBPrIyFnF51g==", "dev": true }, "mime-db": { @@ -5149,13 +5149,30 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", + "dev": true, + "requires": { + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, "parse5": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "@types/node": "6.0.52" + "@types/node": "7.0.43" } }, "path-dirname": { @@ -6671,9 +6688,9 @@ } }, "vsce": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.32.0.tgz", - "integrity": "sha1-EN+pIyGCwg6r5r8xJdMzpLIG/j0=", + "version": "1.33.2", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.33.2.tgz", + "integrity": "sha1-NkX2mq+YTiL3TqSdNfON0Y1m/18=", "dev": true, "requires": { "cheerio": "1.0.0-rc.2", @@ -6682,9 +6699,10 @@ "glob": "7.1.2", "lodash": "4.17.4", "markdown-it": "8.4.0", - "mime": "1.4.1", + "mime": "1.5.0", "minimatch": "3.0.4", "osenv": "0.1.4", + "parse-semver": "1.1.1", "read": "1.0.7", "semver": "5.4.1", "tmp": "0.0.29", @@ -6709,9 +6727,9 @@ } }, "vscode": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.6.tgz", - "integrity": "sha1-Ru0a+iwbnWifY5TI8WvR1xkPdfs=", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.8.tgz", + "integrity": "sha512-kT6sIA1AEKR5M+us2fXk5dxwV9SR/IEdLHNmVW4/dl1wNBHoEvgIo1qMQwHNxPVTQmw70KTGZ9UVeVb8FbpNFA==", "dev": true, "requires": { "glob": "7.1.2", @@ -6739,34 +6757,26 @@ } }, "vscode-debugadapter": { - "version": "1.25.0-pre.0", - "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0-pre.0.tgz", - "integrity": "sha1-0pDsVH5h5Pvss2P/9ojSAyMZQmQ=", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0.tgz", + "integrity": "sha512-tsOtNNKKTbnQanARdkFfUxI8qKVKba+QHOKWC1reDDeeyvzoNKkLMGkL/xsiKn5vQDeaP3zFBcLY8Ysak9GrvQ==", "requires": { - "vscode-debugprotocol": "1.25.0-pre.0" - }, - "dependencies": { - "vscode-debugprotocol": { - "version": "1.25.0-pre.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0-pre.0.tgz", - "integrity": "sha1-rYPnvZWxmseV31D6Di/pA0YqcrY=" - } + "vscode-debugprotocol": "1.25.0" } }, "vscode-debugadapter-testsupport": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.24.0.tgz", - "integrity": "sha1-rDZ1scU/wW+1JMvSt+znEhtiXng=", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.25.0.tgz", + "integrity": "sha512-6E2N7CoH7B0KEDvI9mFVFt4H+dRFDhtj3PmLVjNojfZ1VZZS2yfhE0XO0E5Axdhef3zTpUU6WZoeOOMVFGZGIg==", "dev": true, "requires": { - "vscode-debugprotocol": "1.24.0" + "vscode-debugprotocol": "1.25.0" } }, "vscode-debugprotocol": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz", - "integrity": "sha1-28EOjX2VsQJyehmvPw/O9+JSsI4=", - "dev": true + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz", + "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" }, "vscode-nls": { "version": "2.0.2", @@ -6774,9 +6784,9 @@ "integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=" }, "vscode-nls-dev": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.5.tgz", - "integrity": "sha1-GfqjsYp/MCIBA5pMlnu9IvoShE0=", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.6.tgz", + "integrity": "sha512-1IylC/ekENYqz1vEItfrzrMXS8LW9aZQnNTU6BfdwT0Jddzed+l+nvU8amgVKFFmC1/GoiMFk5wtC20zWBbEbw==", "dev": true, "requires": { "clone": "1.0.3", diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index 1997b63f7f7..780ff87b24b 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -13,8 +13,8 @@ }, "dependencies": { "semver": "4.3.6", - "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "2.0.1" + "vscode-extension-telemetry": "^0.0.8", + "vscode-nls": "^2.0.2" }, "devDependencies": { "@types/node": "8.0.33", diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index f3800d5cd10..fb8fd36867d 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -399,8 +399,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } private snippetForFunctionCall(detail: CompletionEntryDetails): SnippetString { - const suggestionArgumentNames: string[] = []; - let hasOptionalParemeters = false; + let hasOptionalParameters = false; + let hasAddedParameters = false; + + const snippet = new SnippetString(); + snippet.appendText(detail.name); + snippet.appendText('('); + let parenCount = 0; let i = 0; for (; i < detail.displayParts.length; ++i) { @@ -411,9 +416,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP // Skip optional parameters const nameIsFollowedByOptionalIndicator = next && next.text === '?'; if (!nameIsFollowedByOptionalIndicator) { - suggestionArgumentNames.push(`\${${i + 1}:${part.text}}`); + if (hasAddedParameters) { + snippet.appendText(', '); + } + hasAddedParameters = true; + snippet.appendPlaceholder(part.text); } - hasOptionalParemeters = hasOptionalParemeters || nameIsFollowedByOptionalIndicator; + hasOptionalParameters = hasOptionalParameters || nameIsFollowedByOptionalIndicator; } else if (part.kind === 'punctuation') { if (part.text === '(') { ++parenCount; @@ -421,13 +430,17 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP --parenCount; } else if (part.text === '...' && parenCount === 1) { // Found rest parmeter. Do not fill in any further arguments - hasOptionalParemeters = true; + hasOptionalParameters = true; break; } } } - const codeSnippet = `${detail.name}(${suggestionArgumentNames.join(', ')}${hasOptionalParemeters ? '${' + i + '}' : ''})$0`; - return new SnippetString(codeSnippet); + if (hasOptionalParameters) { + snippet.appendTabstop(); + } + snippet.appendText(')'); + snippet.appendTabstop(0); + return snippet; } private getConfiguration(resource: Uri): Configuration { diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index 89964180240..e823eaba480 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -27,6 +27,7 @@ import { TypeScriptServiceConfiguration, TsServerLogLevel } from './utils/config import { TypeScriptVersionProvider, TypeScriptVersion } from './utils/versionProvider'; import { TypeScriptVersionPicker } from './utils/versionPicker'; import * as fileSchemes from './utils/fileSchemes'; +import { inferredProjectConfig } from './utils/tsconfig'; const localize = nls.loadMessageBundle(); @@ -330,11 +331,9 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient this.error('Starting TSServer failed with error.', err); window.showErrorMessage(localize('serverCouldNotBeStarted', 'TypeScript language server couldn\'t be started. Error message is: {0}', err.message || err)); /* __GDPR__ - "error" : { - "message": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" } - } + "error" : {} */ - this.logTelemetry('error', { message: err.message }); + this.logTelemetry('error'); this.resetClientVersion(); return; } @@ -476,20 +475,12 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient } private getCompilerOptionsForInferredProjects(configuration: TypeScriptServiceConfiguration): Proto.ExternalProjectCompilerOptions { - const compilerOptions: Proto.ExternalProjectCompilerOptions = { - module: 'CommonJS' as Proto.ModuleKind, - target: 'ES6' as Proto.ScriptTarget, + return { + ...inferredProjectConfig(configuration), + allowJs: true, allowSyntheticDefaultImports: true, allowNonTsExtensions: true, - allowJs: true, - jsx: 'Preserve' as Proto.JsxEmit }; - - if (this.apiVersion.has230Features()) { - compilerOptions.checkJs = configuration.checkJs; - compilerOptions.experimentalDecorators = configuration.experimentalDecorators; - } - return compilerOptions; } private serviceExited(restart: boolean): void { diff --git a/extensions/typescript/src/utils/tsconfig.ts b/extensions/typescript/src/utils/tsconfig.ts index fd65741cf5b..91293a8cc11 100644 --- a/extensions/typescript/src/utils/tsconfig.ts +++ b/extensions/typescript/src/utils/tsconfig.ts @@ -5,27 +5,39 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import * as Proto from '../protocol'; + import { TypeScriptServiceConfiguration } from './configuration'; export function isImplicitProjectConfigFile(configFileName: string) { return configFileName.indexOf('/dev/null/') === 0; } -function getEmptyConfig( - isTypeScriptProject: boolean, +export function inferredProjectConfig( + config: TypeScriptServiceConfiguration +): Proto.ExternalProjectCompilerOptions { + const base: Proto.ExternalProjectCompilerOptions = { + module: 'commonjs' as Proto.ModuleKind, + target: 'es2016' as Proto.ScriptTarget, + jsx: 'preserve' as Proto.JsxEmit + }; + + if (config.checkJs) { + base.checkJs = true; + } + + if (config.experimentalDecorators) { + base.experimentalDecorators = true; + } + + return base; +} + +function inferredProjectConfigSnippet( config: TypeScriptServiceConfiguration ) { - const compilerOptions = [ - '"target": "ES6"', - '"module": "commonjs"', - '"jsx": "preserve"', - ]; - if (!isTypeScriptProject && config.checkJs) { - compilerOptions.push('"checkJs": true'); - } - if (!isTypeScriptProject && config.experimentalDecorators) { - compilerOptions.push('"experimentalDecorators": true'); - } + const baseConfig = inferredProjectConfig(config); + const compilerOptions = Object.keys(baseConfig).map(key => `"${key}": ${JSON.stringify(baseConfig[key])}`); return new vscode.SnippetString(`{ "compilerOptions": { ${compilerOptions.join(',\n\t\t')}$0 @@ -51,7 +63,7 @@ export async function openOrCreateConfigFile( const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' })); const editor = await vscode.window.showTextDocument(doc, col); if (editor.document.getText().length === 0) { - await editor.insertSnippet(getEmptyConfig(isTypeScriptProject, config)); + await editor.insertSnippet(inferredProjectConfigSnippet(config)); } return editor; } diff --git a/extensions/typescript/yarn.lock b/extensions/typescript/yarn.lock index 7f42682066e..eb4fd8e25fd 100644 --- a/extensions/typescript/yarn.lock +++ b/extensions/typescript/yarn.lock @@ -18,16 +18,16 @@ semver@4.3.6: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" -vscode-extension-telemetry@0.0.8: +vscode-extension-telemetry@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0" dependencies: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.1.tgz#7853866e33f9c50ca415e51b9640d081800e36c6" +vscode-nls@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" winreg@1.2.3: version "1.2.3" diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index f62b80f5f79..b9a95fa62c9 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -10,14 +10,21 @@ set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5% :: Tests in the extension host call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% :: Integration & performance tests in AMD call .\scripts\test.bat --runGlob **\*.integrationTest.js %* +if %errorlevel% neq 0 exit /b %errorlevel% :: Tests in commonJS (language servers tests...) call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\html\server\out\test\ +if %errorlevel% neq 0 exit /b %errorlevel% rmdir /s /q %VSCODEUSERDATADIR% diff --git a/src/vs/code/electron-main/diagnostics.ts b/src/vs/code/electron-main/diagnostics.ts index 285e9c504a6..23813aeaec6 100644 --- a/src/vs/code/electron-main/diagnostics.ts +++ b/src/vs/code/electron-main/diagnostics.ts @@ -124,7 +124,7 @@ function formatEnvironment(info: IMainProcessInfo): string { const output: string[] = []; output.push(`Version: ${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`); - output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()})`); + output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()}`); const cpus = os.cpus(); if (cpus && cpus.length > 0) { output.push(`CPUs: ${cpus[0].model} (${cpus.length} x ${cpus[0].speed})`); diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 08c9c688aed..f67e5b4e7cc 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -472,8 +472,8 @@ export class View extends ViewEventHandler { return this.outgoingEvents; } - public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): OverviewRuler { - return new OverviewRuler(this._context, cssClassName, minimumHeight, maximumHeight); + public createOverviewRuler(cssClassName: string): OverviewRuler { + return new OverviewRuler(this._context, cssClassName); } public change(callback: (changeAccessor: editorBrowser.IViewZoneChangeAccessor) => any): boolean { diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index d5f1311d3b1..1b450611c58 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -11,38 +11,23 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions'; import { OverviewRulerZone, OverviewZoneManager, ColorZone } from 'vs/editor/common/view/overviewZoneManager'; import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode'; -import { Color } from 'vs/base/common/color'; -import { LIGHT } from 'vs/platform/theme/common/themeService'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { private _context: ViewContext; - private _canvasLeftOffset: number; private _domNode: FastDomNode; - private _lanesCount: number; private _zoneManager: OverviewZoneManager; - private _background: Color; - constructor(context: ViewContext, cssClassName: string, minimumHeight: number, maximumHeight: number) { + constructor(context: ViewContext, cssClassName: string) { super(); this._context = context; - this._canvasLeftOffset = 0; - this._domNode = createFastDomNode(document.createElement('canvas')); this._domNode.setClassName(cssClassName); this._domNode.setPosition('absolute'); this._domNode.setLayerHinting(true); - this._lanesCount = 3; - - this._background = null; - this._zoneManager = new OverviewZoneManager((lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber)); - this._zoneManager.setMinimumHeight(minimumHeight); - this._zoneManager.setMaximumHeight(maximumHeight); - this._zoneManager.setThemeType(LIGHT); this._zoneManager.setDOMWidth(0); this._zoneManager.setDOMHeight(0); this._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight()); @@ -64,7 +49,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { if (e.lineHeight) { this._zoneManager.setLineHeight(this._context.configuration.editor.lineHeight); - this.render(true); + this._render(); } if (e.pixelRatio) { @@ -73,23 +58,24 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._domNode.setHeight(this._zoneManager.getDOMHeight()); this._domNode.domNode.width = this._zoneManager.getCanvasWidth(); this._domNode.domNode.height = this._zoneManager.getCanvasHeight(); - this.render(true); + this._render(); } return true; } - public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { + this._render(); return true; } - public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { - this._zoneManager.setOuterHeight(e.scrollHeight); - this.render(true); - return super.onScrollChanged(e) || e.scrollHeightChanged; + if (e.scrollHeightChanged) { + this._zoneManager.setOuterHeight(e.scrollHeight); + this._render(); + } + return true; } - public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean { + this._render(); return true; } @@ -113,16 +99,16 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._domNode.domNode.width = this._zoneManager.getCanvasWidth(); this._domNode.domNode.height = this._zoneManager.getCanvasHeight(); - this.render(true); + this._render(); } } public setZones(zones: OverviewRulerZone[]): void { this._zoneManager.setZones(zones); - this.render(false); + this._render(); } - public render(forceRender: boolean): boolean { + private _render(): boolean { if (this._zoneManager.getOuterHeight() === 0) { return false; } @@ -134,79 +120,29 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { let id2Color = this._zoneManager.getId2Color(); let ctx = this._domNode.domNode.getContext('2d'); - if (this._background === null) { - ctx.clearRect(0, 0, width, height); - } else { - ctx.fillStyle = Color.Format.CSS.formatHex(this._background); - ctx.fillRect(0, 0, width, height); - } - + ctx.clearRect(0, 0, width, height); if (colorZones.length > 0) { - let remainingWidth = width - this._canvasLeftOffset; - - if (this._lanesCount >= 3) { - this._renderThreeLanes(ctx, colorZones, id2Color, remainingWidth); - } else if (this._lanesCount === 2) { - this._renderTwoLanes(ctx, colorZones, id2Color, remainingWidth); - } else if (this._lanesCount === 1) { - this._renderOneLane(ctx, colorZones, id2Color, remainingWidth); - } + this._renderOneLane(ctx, colorZones, id2Color, width); } return true; } - - private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center | OverviewRulerLane.Right, this._canvasLeftOffset, w); - - } - - private _renderTwoLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - let leftWidth = Math.floor(w / 2); - let rightWidth = w - leftWidth; - let leftOffset = this._canvasLeftOffset; - let rightOffset = this._canvasLeftOffset + leftWidth; - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center, leftOffset, leftWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth); - } - - private _renderThreeLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void { - - let leftWidth = Math.floor(w / 3); - let rightWidth = Math.floor(w / 3); - let centerWidth = w - leftWidth - rightWidth; - let leftOffset = this._canvasLeftOffset; - let centerOffset = this._canvasLeftOffset + leftWidth; - let rightOffset = this._canvasLeftOffset + leftWidth + centerWidth; - - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left, leftOffset, leftWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Center, centerOffset, centerWidth); - this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth); - } - - private _renderVerticalPatch(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], laneMask: number, xpos: number, width: number): void { + private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], width: number): void { let currentColorId = 0; let currentFrom = 0; let currentTo = 0; for (let i = 0, len = colorZones.length; i < len; i++) { - let zone = colorZones[i]; + const zone = colorZones[i]; - if (!(zone.position & laneMask)) { - continue; - } - - let zoneColorId = zone.colorId; - let zoneFrom = zone.from; - let zoneTo = zone.to; + const zoneColorId = zone.colorId; + const zoneFrom = zone.from; + const zoneTo = zone.to; if (zoneColorId !== currentColorId) { - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); currentColorId = zoneColorId; ctx.fillStyle = id2Color[currentColorId]; @@ -216,14 +152,14 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { if (currentTo >= zoneFrom) { currentTo = Math.max(currentTo, zoneTo); } else { - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); currentFrom = zoneFrom; currentTo = zoneTo; } } } - ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom); + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); } } diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 34eb4d6e194..52c8dd723d2 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -157,8 +157,8 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito super.dispose(); } - public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): editorBrowser.IOverviewRuler { - return this._view.createOverviewRuler(cssClassName, minimumHeight, maximumHeight); + public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler { + return this._view.createOverviewRuler(cssClassName); } public getDomNode(): HTMLElement { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 34bfc9c3f15..23eaa557d14 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -361,14 +361,14 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode()); this._originalOverviewRuler.dispose(); } - this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler', 4, Number.MAX_VALUE); + this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler'); this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode()); if (this._modifiedOverviewRuler) { this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode()); this._modifiedOverviewRuler.dispose(); } - this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler', 4, Number.MAX_VALUE); + this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler'); this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode()); this._layoutOverviewRulers(); @@ -1594,6 +1594,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd } _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._removeColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1614,16 +1615,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, DECORATIONS.charDeleteWholeLine)); } - let color = this._removeColor.toString(); - result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, - color + overviewZoneColor )); if (lineChange.charChanges) { @@ -1659,6 +1654,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd } _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._insertColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1679,15 +1675,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); } - let color = this._insertColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, - color + overviewZoneColor )); if (lineChange.charChanges) { @@ -1783,6 +1774,8 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._removeColor.toString(); + let result: IEditorDiffDecorations = { decorations: [], overviewZones: [] @@ -1798,15 +1791,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor options: DECORATIONS.lineDeleteMargin }); - let color = this._removeColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, - color + overviewZoneColor )); } } @@ -1815,6 +1803,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations { + const overviewZoneColor = this._insertColor.toString(); let result: IEditorDiffDecorations = { decorations: [], @@ -1833,15 +1822,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); - let color = this._insertColor.toString(); result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, - editorCommon.OverviewRulerLane.Full, - 0, - color, - color, - color + overviewZoneColor )); if (lineChange.charChanges) { diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index 8bbf6e5e685..92759f72bbe 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -4,22 +4,31 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; -import { ThemeType, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService'; +const enum Constants { + MINIMUM_HEIGHT = 4 +} export class ColorZone { _colorZoneBrand: void; - from: number; - to: number; - colorId: number; - position: OverviewRulerLane; + public readonly from: number; + public readonly to: number; + public readonly colorId: number; - constructor(from: number, to: number, colorId: number, position: OverviewRulerLane) { + constructor(from: number, to: number, colorId: number) { this.from = from | 0; this.to = to | 0; this.colorId = colorId | 0; - this.position = position | 0; + } + + public static compare(a: ColorZone, b: ColorZone): number { + if (a.colorId === b.colorId) { + if (a.from === b.from) { + return a.to - b.to; + } + return a.from - b.from; + } + return a.colorId - b.colorId; } } @@ -29,74 +38,39 @@ export class ColorZone { export class OverviewRulerZone { _overviewRulerZoneBrand: void; - startLineNumber: number; - endLineNumber: number; - position: OverviewRulerLane; - forceHeight: number; + public readonly startLineNumber: number; + public readonly endLineNumber: number; + public readonly color: string; - private _color: string; - private _darkColor: string; - private _hcColor: string; - - private _colorZones: ColorZone[]; + private _colorZone: ColorZone; constructor( - startLineNumber: number, endLineNumber: number, - position: OverviewRulerLane, - forceHeight: number, - color: string, darkColor: string, hcColor: string + startLineNumber: number, + endLineNumber: number, + color: string ) { this.startLineNumber = startLineNumber; this.endLineNumber = endLineNumber; - this.position = position; - this.forceHeight = forceHeight; - this._color = color; - this._darkColor = darkColor; - this._hcColor = hcColor; - this._colorZones = null; + this.color = color; + this._colorZone = null; } - public getColor(themeType: ThemeType): string { - switch (themeType) { - case HIGH_CONTRAST: - return this._hcColor; - case DARK: - return this._darkColor; - } - return this._color; - } - - public compareTo(other: OverviewRulerZone): number { - if (this.startLineNumber === other.startLineNumber) { - if (this.endLineNumber === other.endLineNumber) { - if (this.forceHeight === other.forceHeight) { - if (this.position === other.position) { - if (this._darkColor === other._darkColor) { - if (this._color === other._color) { - if (this._hcColor === other._hcColor) { - return 0; - } - return this._hcColor < other._hcColor ? -1 : 1; - } - return this._color < other._color ? -1 : 1; - } - return this._darkColor < other._darkColor ? -1 : 1; - } - return this.position - other.position; - } - return this.forceHeight - other.forceHeight; + public static compare(a: OverviewRulerZone, b: OverviewRulerZone): number { + if (a.color === b.color) { + if (a.startLineNumber === b.startLineNumber) { + return a.endLineNumber - b.endLineNumber; } - return this.endLineNumber - other.endLineNumber; + return a.startLineNumber - b.startLineNumber; } - return this.startLineNumber - other.startLineNumber; + return a.color < b.color ? -1 : 1; } - public setColorZones(colorZones: ColorZone[]): void { - this._colorZones = colorZones; + public setColorZone(colorZone: ColorZone): void { + this._colorZone = colorZone; } - public getColorZones(): ColorZone[] { - return this._colorZones; + public getColorZones(): ColorZone { + return this._colorZone; } } @@ -109,9 +83,6 @@ export class OverviewZoneManager { private _domWidth: number; private _domHeight: number; private _outerHeight: number; - private _maximumHeight: number; - private _minimumHeight: number; - private _themeType: ThemeType; private _pixelRatio: number; private _lastAssignedId: number; @@ -126,9 +97,6 @@ export class OverviewZoneManager { this._domWidth = 0; this._domHeight = 0; this._outerHeight = 0; - this._maximumHeight = 0; - this._minimumHeight = 0; - this._themeType = LIGHT; this._pixelRatio = 1; this._lastAssignedId = 0; @@ -141,39 +109,8 @@ export class OverviewZoneManager { } public setZones(newZones: OverviewRulerZone[]): void { - newZones.sort((a, b) => a.compareTo(b)); - - let oldZones = this._zones; - let oldIndex = 0; - let oldLength = this._zones.length; - let newIndex = 0; - let newLength = newZones.length; - - let result: OverviewRulerZone[] = []; - while (newIndex < newLength) { - let newZone = newZones[newIndex]; - - if (oldIndex >= oldLength) { - result.push(newZone); - newIndex++; - } else { - let oldZone = oldZones[oldIndex]; - let cmp = oldZone.compareTo(newZone); - if (cmp < 0) { - oldIndex++; - } else if (cmp > 0) { - result.push(newZone); - newIndex++; - } else { - // cmp === 0 - result.push(oldZone); - oldIndex++; - newIndex++; - } - } - } - - this._zones = result; + this._zones = newZones; + this._zones.sort(OverviewRulerZone.compare); } public setLineHeight(lineHeight: number): boolean { @@ -237,146 +174,58 @@ export class OverviewZoneManager { return true; } - public setMaximumHeight(maximumHeight: number): boolean { - if (this._maximumHeight === maximumHeight) { - return false; - } - this._maximumHeight = maximumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setMinimumHeight(minimumHeight: number): boolean { - if (this._minimumHeight === minimumHeight) { - return false; - } - this._minimumHeight = minimumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setThemeType(themeType: ThemeType): boolean { - if (this._themeType === themeType) { - return false; - } - this._themeType = themeType; - this._colorZonesInvalid = true; - return true; - } - public resolveColorZones(): ColorZone[] { const colorZonesInvalid = this._colorZonesInvalid; const lineHeight = Math.floor(this._lineHeight); // @perf const totalHeight = Math.floor(this.getCanvasHeight()); // @perf - const maximumHeight = Math.floor(this._maximumHeight * this._pixelRatio); // @perf - const minimumHeight = Math.floor(this._minimumHeight * this._pixelRatio); // @perf - const themeType = this._themeType; // @perf const outerHeight = Math.floor(this._outerHeight); // @perf const heightRatio = totalHeight / outerHeight; let allColorZones: ColorZone[] = []; for (let i = 0, len = this._zones.length; i < len; i++) { - let zone = this._zones[i]; + const zone = this._zones[i]; if (!colorZonesInvalid) { - let colorZones = zone.getColorZones(); - if (colorZones) { - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); - } + const colorZone = zone.getColorZones(); + if (colorZone) { + allColorZones.push(colorZone); continue; } } - let colorZones: ColorZone[] = []; - if (zone.forceHeight) { - let forcedHeight = Math.floor(zone.forceHeight * this._pixelRatio); + const y1 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.startLineNumber))); + const y2 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight)); - let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); - y1 = Math.floor(y1 * heightRatio); + let ycenter = Math.floor((y1 + y2) / 2); + let halfHeight = (y2 - ycenter); - let y2 = y1 + forcedHeight; - colorZones.push(this.createZone(totalHeight, y1, y2, forcedHeight, forcedHeight, zone.getColor(themeType), zone.position)); - } else { - let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); - let y2 = Math.floor(this._getVerticalOffsetForLine(zone.endLineNumber)) + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - // Figure out if we can render this in one continuous zone - let zoneLineNumbers = zone.endLineNumber - zone.startLineNumber + 1; - let zoneMaximumHeight = zoneLineNumbers * maximumHeight; - - if (y2 - y1 > zoneMaximumHeight) { - // We need to draw one zone per line - for (let lineNumber = zone.startLineNumber; lineNumber <= zone.endLineNumber; lineNumber++) { - y1 = Math.floor(this._getVerticalOffsetForLine(lineNumber)); - y2 = y1 + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, maximumHeight, zone.getColor(themeType), zone.position)); - } - } else { - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, zoneMaximumHeight, zone.getColor(themeType), zone.position)); - } + if (halfHeight < Constants.MINIMUM_HEIGHT / 2) { + halfHeight = Constants.MINIMUM_HEIGHT / 2; } - zone.setColorZones(colorZones); - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); + if (ycenter - halfHeight < 0) { + ycenter = halfHeight; } + if (ycenter + halfHeight > totalHeight) { + ycenter = totalHeight - halfHeight; + } + + const color = zone.color; + let colorId = this._color2Id[color]; + if (!colorId) { + colorId = (++this._lastAssignedId); + this._color2Id[color] = colorId; + this._id2Color[colorId] = color; + } + const colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId); + + zone.setColorZone(colorZone); + allColorZones.push(colorZone); } this._colorZonesInvalid = false; - let sortFunc = (a: ColorZone, b: ColorZone) => { - if (a.colorId === b.colorId) { - if (a.from === b.from) { - return a.to - b.to; - } - return a.from - b.from; - } - return a.colorId - b.colorId; - }; - - allColorZones.sort(sortFunc); + allColorZones.sort(ColorZone.compare); return allColorZones; } - - public createZone(totalHeight: number, y1: number, y2: number, minimumHeight: number, maximumHeight: number, color: string, position: OverviewRulerLane): ColorZone { - totalHeight = Math.floor(totalHeight); // @perf - y1 = Math.floor(y1); // @perf - y2 = Math.floor(y2); // @perf - minimumHeight = Math.floor(minimumHeight); // @perf - maximumHeight = Math.floor(maximumHeight); // @perf - - let ycenter = Math.floor((y1 + y2) / 2); - let halfHeight = (y2 - ycenter); - - - if (halfHeight > maximumHeight / 2) { - halfHeight = maximumHeight / 2; - } - if (halfHeight < minimumHeight / 2) { - halfHeight = minimumHeight / 2; - } - - if (ycenter - halfHeight < 0) { - ycenter = halfHeight; - } - if (ycenter + halfHeight > totalHeight) { - ycenter = totalHeight - halfHeight; - } - - let colorId = this._color2Id[color]; - if (!colorId) { - colorId = (++this._lastAssignedId); - this._color2Id[color] = colorId; - this._id2Color[colorId] = color; - } - return new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId, position); - } } diff --git a/src/vs/editor/test/common/view/overviewZoneManager.test.ts b/src/vs/editor/test/common/view/overviewZoneManager.test.ts index 1cfc1a4a2b1..1781b29855b 100644 --- a/src/vs/editor/test/common/view/overviewZoneManager.test.ts +++ b/src/vs/editor/test/common/view/overviewZoneManager.test.ts @@ -5,9 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { OverviewRulerLane } from 'vs/editor/common/editorCommon'; import { OverviewZoneManager, ColorZone, OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager'; -import { LIGHT } from 'vs/platform/theme/common/themeService'; suite('Editor View - OverviewZoneManager', () => { @@ -15,9 +13,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(600); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -25,19 +20,18 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(1); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 12, but cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(12, 22, 1, OverviewRulerLane.Full), // forced height of 10 - new ColorZone(123, 129, 2, OverviewRulerLane.Full), // 120 -> 132 - new ColorZone(363, 369, 3, OverviewRulerLane.Full), // 360 -> 372 [360 -> 384] - new ColorZone(375, 381, 3, OverviewRulerLane.Full), // 372 -> 384 [360 -> 384] - new ColorZone(594, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + new ColorZone(12, 24, 1), // + new ColorZone(120, 132, 2), // 120 -> 132 + new ColorZone(360, 384, 3), // 360 -> 372 [360 -> 384] + new ColorZone(588, 600, 4), // 588 -> 600 ]); }); @@ -45,9 +39,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(300); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -55,18 +46,18 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(1); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 6, cap is at 6 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(6, 16, 1, OverviewRulerLane.Full), // forced height of 10 - new ColorZone(60, 66, 2, OverviewRulerLane.Full), // 60 -> 66 - new ColorZone(180, 192, 3, OverviewRulerLane.Full), // 180 -> 192 - new ColorZone(294, 300, 4, OverviewRulerLane.Full), // 294 -> 300 + new ColorZone(6, 12, 1), // + new ColorZone(60, 66, 2), // 60 -> 66 + new ColorZone(180, 192, 3), // 180 -> 192 + new ColorZone(294, 300, 4), // 294 -> 300 ]); }); @@ -74,9 +65,6 @@ suite('Editor View - OverviewZoneManager', () => { const LINE_COUNT = 50; const LINE_HEIGHT = 20; let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); - manager.setMinimumHeight(6); - manager.setMaximumHeight(6); - manager.setThemeType(LIGHT); manager.setDOMWidth(30); manager.setDOMHeight(300); manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); @@ -84,18 +72,18 @@ suite('Editor View - OverviewZoneManager', () => { manager.setPixelRatio(2); manager.setZones([ - new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'), - new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'), - new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'), - new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'), + new OverviewRulerZone(1, 1, '1'), + new OverviewRulerZone(10, 10, '2'), + new OverviewRulerZone(30, 31, '3'), + new OverviewRulerZone(50, 50, '4'), ]); // one line = 6, cap is at 12 assert.deepEqual(manager.resolveColorZones(), [ - new ColorZone(12, 32, 1, OverviewRulerLane.Full), // forced height of 10 => forced height of 20 - new ColorZone(120, 132, 2, OverviewRulerLane.Full), // 120 -> 132 - new ColorZone(360, 384, 3, OverviewRulerLane.Full), // 360 -> 384 - new ColorZone(588, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + new ColorZone(12, 24, 1), // + new ColorZone(120, 132, 2), // 120 -> 132 + new ColorZone(360, 384, 3), // 360 -> 384 + new ColorZone(588, 600, 4), // 588 -> 600 ]); }); }); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index b02773f70b9..86982258339 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5782,6 +5782,11 @@ declare module 'vscode' { * A string to show as place holder in the input box to guide the user. */ placeholder: string; + + /** + * The warning threshold for lines in the input box. + */ + lineWarningLength: number | undefined; } interface QuickDiffProvider { diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 88c6377b3c4..2541503baa9 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -391,4 +391,14 @@ export class MainThreadSCM implements MainThreadSCMShape { repository.input.placeholder = placeholder; } + + $setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void { + const repository = this._repositories[sourceControlHandle]; + + if (!repository) { + return; + } + + repository.input.lineWarningLength = lineWarningLength; + } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 111a4643be8..f9fd93dfa20 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -410,6 +410,7 @@ export interface MainThreadSCMShape extends IDisposable { $setInputBoxValue(sourceControlHandle: number, value: string): void; $setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void; + $setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void; } export type DebugSessionUUID = string; diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 9444ef00744..37a6b752ab1 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -110,7 +110,7 @@ function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.S return result; } -export class ExtHostSCMInputBox { +export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { private _value: string = ''; @@ -140,6 +140,17 @@ export class ExtHostSCMInputBox { this._placeholder = placeholder; } + private _lineWarningLength: number | undefined; + + get lineWarningLength(): number | undefined { + return this._lineWarningLength; + } + + set lineWarningLength(lineWarningLength: number) { + this._proxy.$setLineWarningLength(this._sourceControlHandle, lineWarningLength); + this._lineWarningLength = lineWarningLength; + } + constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) { // noop } diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 0238302847f..7bc93ba609f 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -580,16 +580,22 @@ export class ViewsViewlet extends PanelViewlet { if (this.length > 1) { return false; } - // Check in cache so that view do not jump. See #29609 - if (ViewLocation.getContributedViewLocation(this.location.id) && !this.areExtensionsReady) { + + if (ViewLocation.getContributedViewLocation(this.location.id)) { let visibleViewsCount = 0; - this.viewsStates.forEach((viewState, id) => { - if (!viewState.isHidden) { - visibleViewsCount++; - } - }); + if (this.areExtensionsReady) { + visibleViewsCount = this.getViewDescriptorsFromRegistry().reduce((visibleViewsCount, v) => visibleViewsCount + (this.canBeVisible(v) ? 1 : 0), 0); + } else { + // Check in cache so that view do not jump. See #29609 + this.viewsStates.forEach((viewState, id) => { + if (!viewState.isHidden) { + visibleViewsCount++; + } + }); + } return visibleViewsCount === 1; } + return super.isSingleView(); } diff --git a/src/vs/workbench/parts/html/browser/webview-pre.js b/src/vs/workbench/parts/html/browser/webview-pre.js index 3cfc357897a..29af803b49c 100644 --- a/src/vs/workbench/parts/html/browser/webview-pre.js +++ b/src/vs/workbench/parts/html/browser/webview-pre.js @@ -46,11 +46,12 @@ if (!event || !event.view || !event.view.document) { return; } + + var baseElement = event.view.document.getElementsByTagName('base')[0]; /** @type {any} */ var node = event.target; while (node) { if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) { - var baseElement = event.view.document.getElementsByTagName('base')[0]; if (node.getAttribute('href') === '#') { event.view.scrollTo(0, 0); } else if (node.hash && (node.getAttribute('href') === node.hash || (baseElement && node.href.indexOf(baseElement.href) >= 0))) { diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/html/browser/webview.ts index 8589995213b..2df1213dadf 100644 --- a/src/vs/workbench/parts/html/browser/webview.ts +++ b/src/vs/workbench/parts/html/browser/webview.ts @@ -196,6 +196,10 @@ export default class Webview { this._onDidClickLink.dispose(); this._disposables = dispose(this._disposables); + if (this._contextKey) { + this._contextKey.reset(); + } + if (this._webview.parentElement) { this._webview.parentElement.removeChild(this._webview); const findWidgetDomNode = this._webviewFindWidget.getDomNode(); diff --git a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts index d2a18a112ea..bce5b81ee3c 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scm.contribution.ts @@ -74,5 +74,11 @@ Registry.as(ConfigurationExtensions.Configuration).regis default: 'all', description: localize('diffDecorations', "Controls diff decorations in the editor.") }, + 'scm.inputCounter': { + type: 'string', + enum: ['always', 'warn', 'off'], + default: 'warn', + description: localize('inputCounter', "Controls when to display the input counter.") + } } }); \ No newline at end of file diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 4530cff6727..af7f2a6a9b6 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/scmViewlet'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; -import Event, { Emitter, chain, mapEvent } from 'vs/base/common/event'; +import Event, { Emitter, chain, mapEvent, anyEvent } from 'vs/base/common/event'; import { domEvent, stop } from 'vs/base/browser/event'; import { basename } from 'vs/base/common/paths'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -45,7 +45,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { IMessage, InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Command } from 'vs/editor/common/modes'; @@ -56,6 +56,7 @@ import { format } from 'vs/base/common/strings'; import { ISpliceable, ISequence, ISplice } from 'vs/base/common/sequence'; import { firstIndex } from 'vs/base/common/arrays'; import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; // TODO@Joao // Need to subclass MenuItemActionItem in order to respect @@ -695,7 +696,8 @@ export class RepositoryPanel extends ViewletPanel { @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IEditorGroupService protected editorGroupService: IEditorGroupService, @IContextKeyService protected contextKeyService: IContextKeyService, - @IInstantiationService protected instantiationService: IInstantiationService + @IInstantiationService protected instantiationService: IInstantiationService, + @IConfigurationService protected configurationService: IConfigurationService ) { super(repository.provider.label, {}, keybindingService, contextMenuService); this.menus = instantiationService.createInstance(SCMMenus, repository.provider); @@ -753,10 +755,63 @@ export class RepositoryPanel extends ViewletPanel { this.inputBox.setPlaceHolder(placeholder); }; - this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { flexibleHeight: true }); + const validation = (text: string): IMessage => { + const setting = this.configurationService.getValue<'always' | 'warn' | 'off'>('scm.inputCounter'); + + if (setting === 'off') { + return null; + } + + let position = this.inputBox.inputElement.selectionStart; + let start = 0, end; + let match: RegExpExecArray; + const regex = /\r?\n/g; + + while ((match = regex.exec(text)) && position > match.index) { + start = match.index + match[0].length; + } + + end = match ? match.index : text.length; + + const line = text.substring(start, end); + + const lineWarningLength = this.repository.input.lineWarningLength; + + if (lineWarningLength === undefined) { + return { + content: localize('commitMessageInfo', "{0} characters in current line", text.length), + type: MessageType.INFO + }; + } + + if (line.length <= lineWarningLength) { + if (setting !== 'always') { + return null; + } + + return { + content: localize('commitMessageCountdown', "{0} characters left in current line", lineWarningLength - line.length), + type: MessageType.INFO + }; + } else { + return { + content: localize('commitMessageWarning', "{0} characters over {1} in current line", line.length - lineWarningLength, lineWarningLength), + type: MessageType.WARNING + }; + } + }; + + this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { + flexibleHeight: true, + validationOptions: { validation: validation } + }); this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService)); this.disposables.push(this.inputBox); + const onKeyUp = domEvent(this.inputBox.inputElement, 'keyup'); + const onMouseUp = domEvent(this.inputBox.inputElement, 'mouseup'); + anyEvent(onKeyUp, onMouseUp)(() => this.inputBox.validate(), null, this.disposables); + this.inputBox.value = this.repository.input.value; this.inputBox.onDidChange(value => this.repository.input.value = value, null, this.disposables); this.repository.input.onDidChange(value => this.inputBox.value = value, null, this.disposables); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f5886a2d038..2bf830a0f1b 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -35,14 +35,13 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; import pkg from 'vs/platform/node/package'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; +import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; -// Enable search functionality in xterm.js instance -XTermTerminal.loadAddon('search'); -// Enable the winpty compatibility addon which will simulate wraparound mode -XTermTerminal.loadAddon('winptyCompat'); +let Terminal: typeof XTermTerminal; enum ProcessState { // The process has not been initialized yet. @@ -97,6 +96,7 @@ export class TerminalInstance implements ITerminalInstance { private _initialCwd: string; private _windowsShellHelper: WindowsShellHelper; private _onLineDataListeners: ((lineData: string) => void)[]; + private _xtermReadyPromise: TPromise; private _widgetManager: TerminalWidgetManager; private _linkHandler: TerminalLinkHandler; @@ -123,7 +123,9 @@ export class TerminalInstance implements ITerminalInstance { @IInstantiationService private _instantiationService: IInstantiationService, @IClipboardService private _clipboardService: IClipboardService, @IHistoryService private _historyService: IHistoryService, - @IThemeService private _themeService: IThemeService + @IThemeService private _themeService: IThemeService, + @IConfigurationResolverService private _configurationResolverService: IConfigurationResolverService, + @IWorkspaceContextService private _workspaceContextService: IWorkspaceContextService ) { this._instanceDisposables = []; this._processDisposables = []; @@ -150,7 +152,6 @@ export class TerminalInstance implements ITerminalInstance { this._initDimensions(); this._createProcess(); - this._createXterm(); if (platform.isWindows) { this._processReady.then(() => { @@ -160,10 +161,13 @@ export class TerminalInstance implements ITerminalInstance { }); } - // Only attach xterm.js to the DOM if the terminal panel has been opened before. - if (_container) { - this.attachToElement(_container); - } + this._xtermReadyPromise = this._createXterm(); + this._xtermReadyPromise.then(() => { + // Only attach xterm.js to the DOM if the terminal panel has been opened before. + if (_container) { + this.attachToElement(_container); + } + }); } public addDisposable(disposable: lifecycle.IDisposable): void { @@ -248,9 +252,16 @@ export class TerminalInstance implements ITerminalInstance { /** * Create xterm.js instance and attach data listeners. */ - protected _createXterm(): void { + protected async _createXterm(): TPromise { + if (!Terminal) { + Terminal = (await import('xterm')).Terminal; + // Enable search functionality in xterm.js instance + Terminal.loadAddon('search'); + // Enable the winpty compatibility addon which will simulate wraparound mode + Terminal.loadAddon('winptyCompat'); + } const font = this._configHelper.getFont(true); - this._xterm = new XTermTerminal({ + this._xterm = new Terminal({ scrollback: this._configHelper.config.scrollback, theme: this._getXtermTheme(), fontFamily: font.fontFamily, @@ -284,100 +295,102 @@ export class TerminalInstance implements ITerminalInstance { } public attachToElement(container: HTMLElement): void { - if (this._wrapperElement) { - throw new Error('The terminal instance has already been attached to a container'); - } - - this._container = container; - this._wrapperElement = document.createElement('div'); - dom.addClass(this._wrapperElement, 'terminal-wrapper'); - this._xtermElement = document.createElement('div'); - - // Attach the xterm object to the DOM, exposing it to the smoke tests - (this._wrapperElement).xterm = this._xterm; - - this._xterm.open(this._xtermElement); - this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => { - // Disable all input if the terminal is exiting - if (this._isExiting) { - return false; + this._xtermReadyPromise.then(() => { + if (this._wrapperElement) { + throw new Error('The terminal instance has already been attached to a container'); } - // Skip processing by xterm.js of keyboard events that resolve to commands described - // within commandsToSkipShell - const standardKeyboardEvent = new StandardKeyboardEvent(event); - const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); - if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { - event.preventDefault(); - return false; - } + this._container = container; + this._wrapperElement = document.createElement('div'); + dom.addClass(this._wrapperElement, 'terminal-wrapper'); + this._xtermElement = document.createElement('div'); - // If tab focus mode is on, tab is not passed to the terminal - if (TabFocus.getTabFocusMode() && event.keyCode === 9) { - return false; - } + // Attach the xterm object to the DOM, exposing it to the smoke tests + (this._wrapperElement).xterm = this._xterm; - return undefined; + this._xterm.open(this._xtermElement); + this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => { + // Disable all input if the terminal is exiting + if (this._isExiting) { + return false; + } + + // Skip processing by xterm.js of keyboard events that resolve to commands described + // within commandsToSkipShell + const standardKeyboardEvent = new StandardKeyboardEvent(event); + const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); + if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { + event.preventDefault(); + return false; + } + + // If tab focus mode is on, tab is not passed to the terminal + if (TabFocus.getTabFocusMode() && event.keyCode === 9) { + return false; + } + + return undefined; + }); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => { + // Wait until mouseup has propagated through the DOM before + // evaluating the new selection state. + setTimeout(() => this._refreshSelectionContextKey(), 0); + })); + + // xterm.js currently drops selection on keyup as we need to handle this case. + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { + // Wait until keyup has propagated through the DOM before evaluating + // the new selection state. + setTimeout(() => this._refreshSelectionContextKey(), 0); + })); + + const xtermHelper: HTMLElement = this._xterm.element.querySelector('.xterm-helpers'); + const focusTrap: HTMLElement = document.createElement('div'); + focusTrap.setAttribute('tabindex', '0'); + dom.addClass(focusTrap, 'focus-trap'); + this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { + let currentElement = focusTrap; + while (!dom.hasClass(currentElement, 'part')) { + currentElement = currentElement.parentElement; + } + const hidePanelElement = currentElement.querySelector('.hide-panel-action'); + hidePanelElement.focus(); + })); + xtermHelper.insertBefore(focusTrap, this._xterm.textarea); + + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); + this._refreshSelectionContextKey(); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { + this._terminalFocusContextKey.set(true); + })); + this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { + this._terminalFocusContextKey.reset(); + this._refreshSelectionContextKey(); + })); + + this._wrapperElement.appendChild(this._xtermElement); + this._widgetManager = new TerminalWidgetManager(this._wrapperElement); + this._linkHandler.setWidgetManager(this._widgetManager); + this._container.appendChild(this._wrapperElement); + + const computedStyle = window.getComputedStyle(this._container); + const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); + const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); + this.layout(new Dimension(width, height)); + this.setVisible(this._isVisible); + this.updateConfig(); + + // If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal + // panel was initialized. + if (this._xterm.getOption('disableStdin')) { + this._attachPressAnyKeyToCloseListener(); + } }); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => { - // Wait until mouseup has propagated through the DOM before - // evaluating the new selection state. - setTimeout(() => this._refreshSelectionContextKey(), 0); - })); - - // xterm.js currently drops selection on keyup as we need to handle this case. - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => { - // Wait until keyup has propagated through the DOM before evaluating - // the new selection state. - setTimeout(() => this._refreshSelectionContextKey(), 0); - })); - - const xtermHelper: HTMLElement = this._xterm.element.querySelector('.xterm-helpers'); - const focusTrap: HTMLElement = document.createElement('div'); - focusTrap.setAttribute('tabindex', '0'); - dom.addClass(focusTrap, 'focus-trap'); - this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => { - let currentElement = focusTrap; - while (!dom.hasClass(currentElement, 'part')) { - currentElement = currentElement.parentElement; - } - const hidePanelElement = currentElement.querySelector('.hide-panel-action'); - hidePanelElement.focus(); - })); - xtermHelper.insertBefore(focusTrap, this._xterm.textarea); - - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => { - this._terminalFocusContextKey.set(true); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => { - this._terminalFocusContextKey.reset(); - this._refreshSelectionContextKey(); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => { - this._terminalFocusContextKey.set(true); - })); - this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => { - this._terminalFocusContextKey.reset(); - this._refreshSelectionContextKey(); - })); - - this._wrapperElement.appendChild(this._xtermElement); - this._widgetManager = new TerminalWidgetManager(this._wrapperElement); - this._linkHandler.setWidgetManager(this._widgetManager); - this._container.appendChild(this._wrapperElement); - - const computedStyle = window.getComputedStyle(this._container); - const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10); - const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10); - this.layout(new Dimension(width, height)); - this.setVisible(this._isVisible); - this.updateConfig(); - - // If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal - // panel was initialized. - if (this._xterm.getOption('disableStdin')) { - this._attachPressAnyKeyToCloseListener(); - } } public registerLinkMatcher(regex: RegExp, handler: (url: string) => void, matchIndex?: number, validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void): number { @@ -585,16 +598,24 @@ export class TerminalInstance implements ITerminalInstance { if (!this._shellLaunchConfig.executable) { this._configHelper.mergeDefaultShellPathAndArgs(this._shellLaunchConfig); } - this._initialCwd = this._getCwd(this._shellLaunchConfig, this._historyService.getLastActiveWorkspaceRoot('file')); + + const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file'); + this._initialCwd = this._getCwd(this._shellLaunchConfig, lastActiveWorkspaceRootUri); + + // Resolve env vars from config and shell + const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); + const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); + const envFromConfig = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot); + const envFromShell = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._shellLaunchConfig.env }, lastActiveWorkspaceRoot); + this._shellLaunchConfig.env = envFromShell; // Merge process env with the env from config - const envFromConfig = { ...process.env }; - const envSettingKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); - TerminalInstance.mergeEnvironments(envFromConfig, this._configHelper.config.env[envSettingKey]); + const parentEnv = { ...process.env }; + TerminalInstance.mergeEnvironments(parentEnv, envFromConfig); // Continue env initialization, merging in the env from the launch // config and adding keys that are needed to create the process - const env = TerminalInstance.createTerminalEnv(envFromConfig, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows); + const env = TerminalInstance.createTerminalEnv(parentEnv, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows); this._process = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], { env, cwd: Uri.parse(path.dirname(require.toUrl('../node/terminalProcess'))).fsPath @@ -636,6 +657,16 @@ export class TerminalInstance implements ITerminalInstance { }, LAUNCHING_DURATION); } + // TODO: Should be protected + private static resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: IStringDictionary, lastActiveWorkspaceRoot: IWorkspaceFolder): IStringDictionary { + Object.keys(env).forEach((key) => { + if (typeof env[key] === 'string') { + env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, env[key]); + } + }); + return env; + } + private _sendPtyDataToXterm(message: { type: string, content: string }): void { if (message.type === 'data') { if (this._widgetManager) { diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts index 608a9e5f8bc..a7f066b25bd 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts @@ -20,6 +20,7 @@ import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybin import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; +import { TPromise } from 'vs/base/common/winjs.base'; class TestTerminalInstance extends TerminalInstance { public _getCwd(shell: IShellLaunchConfig, root: Uri): string { @@ -27,7 +28,7 @@ class TestTerminalInstance extends TerminalInstance { } protected _createProcess(): void { } - protected _createXterm(): void { } + protected _createXterm(): TPromise { return TPromise.as(void 0); } } suite('Workbench - TerminalInstance', () => { diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index c1551e21910..29546e8fb3d 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -10,7 +10,6 @@ import fs = require('fs'); import os = require('os'); import crypto = require('crypto'); import assert = require('assert'); -import sudoPrompt = require('sudo-prompt'); import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData } from 'vs/platform/files/common/files'; import { MAX_FILE_SIZE } from 'vs/platform/files/node/files'; @@ -598,14 +597,16 @@ export class FileService implements IFileService { return this.updateContent(uri.file(tmpPath), value, writeOptions).then(() => { // 3.) invoke our CLI as super user - return new TPromise((c, e) => { - const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath }; - sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => { - if (error || stderr) { - e(error || stderr); - } else { - c(void 0); - } + return (import('sudo-prompt')).then(sudoPrompt => { + return new TPromise((c, e) => { + const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath }; + sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => { + if (error || stderr) { + e(error || stderr); + } else { + c(void 0); + } + }); }); }).then(() => { diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index 78c1252f599..78014460542 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -74,6 +74,8 @@ export interface ISCMInput { placeholder: string; readonly onDidChangePlaceholder: Event; + + lineWarningLength: number | undefined; } export interface ISCMRepository extends IDisposable { diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index db569fc7c57..ad66331ddc1 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -39,6 +39,8 @@ class SCMInput implements ISCMInput { private _onDidChangePlaceholder = new Emitter(); get onDidChangePlaceholder(): Event { return this._onDidChangePlaceholder.event; } + + public lineWarningLength: number | undefined = undefined; } class SCMRepository implements ISCMRepository { @@ -106,4 +108,4 @@ export class SCMService implements ISCMService { return repository; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts index cdc6ada67da..2a18075876d 100644 --- a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts @@ -306,5 +306,10 @@ suite('Search-integration', function () { }); function makeExpression(...patterns: string[]): glob.IExpression { - return patterns.reduce((glob, cur) => { glob[cur] = true; return glob; }, Object.create(null)); -} \ No newline at end of file + return patterns.reduce((glob, pattern) => { + // glob.ts needs forward slashes + pattern = pattern.replace(/\\/g, '/'); + glob[pattern] = true; + return glob; + }, Object.create(null)); +}