Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229 (#8962)

* Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229

* skip failing tests

* update mac build image
This commit is contained in:
Anthony Dresser
2020-01-27 15:28:17 -08:00
committed by Karl Burtram
parent 0eaee18dc4
commit fefe1454de
481 changed files with 12764 additions and 7836 deletions

View File

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

View File

@@ -17,6 +17,6 @@ jobs:
- job: macOS
pool:
vmImage: macOS 10.13
vmImage: macOS-latest
steps:
- template: build/azure-pipelines/darwin/continuous-build-darwin.yml

View File

@@ -102,7 +102,7 @@ jobs:
- job: macOS
condition: and(succeeded(), eq(variables['VSCODE_COMPILE_ONLY'], 'false'), eq(variables['VSCODE_BUILD_MACOS'], 'true'))
pool:
vmImage: macOS 10.13
vmImage: macOS-latest
dependsOn:
- Compile
steps:

View File

@@ -15,7 +15,7 @@ jobs:
- job: macOS
condition: eq(variables['VSCODE_BUILD_MACOS'], 'true')
pool:
vmImage: macOS 10.13
vmImage: macOS-latest
dependsOn:
- Compile
steps:

View File

@@ -10,6 +10,7 @@ const os = require('os');
const { remote } = require('electron');
const dialog = remote.dialog;
const productJsonPath = path.join(__dirname, '..', '..', 'product.json');
const builtInExtensionsPath = path.join(__dirname, '..', 'builtInExtensions.json');
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
@@ -51,6 +52,7 @@ function render(el, state) {
}
const ul = document.createElement('ul');
const { quality } = readJson(productJsonPath);
const { builtin, control } = state;
for (const ext of builtin) {
@@ -61,6 +63,10 @@ function render(el, state) {
const name = document.createElement('code');
name.textContent = ext.name;
if (quality && ext.forQualities && !ext.forQualities.includes(quality)) {
name.textContent += ` (only on ${ext.forQualities.join(', ')})`;
}
li.appendChild(name);
const form = document.createElement('form');
@@ -123,4 +129,4 @@ function main() {
render(el, { builtin, control });
}
window.onload = main;
window.onload = main;

View File

@@ -27,6 +27,7 @@ const util = require('./util');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
const product = require('../../product.json');
function fromLocal(extensionPath) {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
const input = fs.existsSync(webpackFilename)
@@ -185,8 +186,8 @@ const excludedExtensions = [
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
'integration-tests'
'integration-tests',
'ms.vscode.js-debug-nightly'
];
// {{SQL CARBON EDIT}}
const externalExtensions = [
@@ -212,7 +213,8 @@ const rebuildExtensions = [
'big-data-cluster',
'mssql'
];
const builtInExtensions = require('../builtInExtensions.json');
const builtInExtensions = require('../builtInExtensions.json')
.filter(({ forQualities }) => { var _a; return !product.quality || ((_a = forQualities === null || forQualities === void 0 ? void 0 : forQualities.includes) === null || _a === void 0 ? void 0 : _a.call(forQualities, product.quality)) !== false; });
function packageLocalExtensionsStream() {
const localExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {

View File

@@ -27,6 +27,7 @@ const util = require('./util');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
const product = require('../../product.json');
function fromLocal(extensionPath: string): Stream {
const webpackFilename = path.join(extensionPath, 'extension.webpack.config.js');
@@ -220,8 +221,8 @@ const excludedExtensions = [
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
'integration-tests'
'integration-tests', // {{SQL CARBON EDIT}}
'ms.vscode.js-debug-nightly'
];
// {{SQL CARBON EDIT}}
@@ -254,10 +255,12 @@ interface IBuiltInExtension {
name: string;
version: string;
repo: string;
forQualities?: ReadonlyArray<string>;
metadata: any;
}
const builtInExtensions: IBuiltInExtension[] = require('../builtInExtensions.json');
const builtInExtensions = (<IBuiltInExtension[]>require('../builtInExtensions.json'))
.filter(({ forQualities }) => !product.quality || forQualities?.includes?.(product.quality) !== false);
export function packageLocalExtensionsStream(): NodeJS.ReadWriteStream {
const localExtensionDescriptions = (<string[]>glob.sync('extensions/*/package.json'))

View File

@@ -6,7 +6,7 @@
"git": {
"name": "chromium",
"repositoryUrl": "https://chromium.googlesource.com/chromium/src",
"commitHash": "e4745133a1d3745f066e068b8033c6a269b59caf"
"commitHash": "91f08db83c2ce8c722ddf0911ead8f7c473bedfa"
}
},
"licenseDetail": [
@@ -40,7 +40,7 @@
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
],
"isOnlyProductionDependency": true,
"version": "78.0.3904.130"
"version": "76.0.3809.146"
},
{
"component": {
@@ -48,11 +48,11 @@
"git": {
"name": "nodejs",
"repositoryUrl": "https://github.com/nodejs/node",
"commitHash": "787378879acfb212ed4ff824bf9f767a24a5cb43a"
"commitHash": "64219741218aa87e259cf8257596073b8e747f0a"
}
},
"isOnlyProductionDependency": true,
"version": "12.8.1"
"version": "12.4.0"
},
{
"component": {
@@ -60,12 +60,12 @@
"git": {
"name": "electron",
"repositoryUrl": "https://github.com/electron/electron",
"commitHash": "bef0dd868b7d6d32716c319664ed480f2ae17396"
"commitHash": "19c705ab80cd6fdccca3d65803ec2c4addb9540a"
}
},
"isOnlyProductionDependency": true,
"license": "MIT",
"version": "7.1.7"
"version": "6.1.6"
},
{
"component": {

View File

@@ -17,6 +17,7 @@
["{", "}"],
["[", "]"],
["(", ")"],
["%", "%"],
["\"", "\""]
],
"folding": {

View File

@@ -24,6 +24,13 @@
"$ref": "vscode://schemas/settings/machine",
"description": "Machine specific settings that should be copied into the container."
},
"forwardPorts": {
"type": "array",
"description": "Ports that are forwarded from the container to the local machine.",
"items": {
"type": "integer"
}
},
"remoteEnv": {
"type": "object",
"additionalProperties": {

View File

@@ -1194,7 +1194,7 @@
{
"command": "git.openFile",
"group": "navigation",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.openChange",
@@ -1204,44 +1204,44 @@
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
}
],
"editor/context": [
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
}
],
"scm/change/title": [
{
"command": "git.stageChange",
"when": "originalResourceScheme == gitfs"
"when": "originalResourceScheme == git"
},
{
"command": "git.revertChange",
"when": "originalResourceScheme == gitfs"
"when": "originalResourceScheme == git"
}
]
},

View File

@@ -239,5 +239,10 @@ export class ApiImpl implements API {
return toGitUri(uri, ref);
}
getRepository(uri: Uri): Repository | null {
const result = this._model.getRepository(uri);
return result ? new ApiRepository(result) : null;
}
constructor(private _model: Model) { }
}

View File

@@ -187,6 +187,7 @@ export interface API {
readonly onDidCloseRepository: Event<Repository>;
toGitUri(uri: Uri, ref: string): Uri;
getRepository(uri: Uri): Repository | null;
}
export interface GitExtension {

View File

@@ -47,9 +47,9 @@ export class GitFileSystemProvider implements FileSystemProvider {
this.disposables.push(
model.onDidChangeRepository(this.onDidChangeRepository, this),
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
workspace.registerFileSystemProvider('gitfs', this, { isReadonly: true, isCaseSensitive: true }),
workspace.registerFileSystemProvider('git', this, { isReadonly: true, isCaseSensitive: true }),
workspace.registerResourceLabelFormatter({
scheme: 'gitfs',
scheme: 'git',
formatting: {
label: '${path} (git)',
separator: '/'

View File

@@ -392,7 +392,7 @@ export class Model {
if (hint instanceof Uri) {
let resourcePath: string;
if (hint.scheme === 'git' || hint.scheme === 'gitfs') {
if (hint.scheme === 'git') {
resourcePath = fromGitUri(hint).path;
} else {
resourcePath = hint.fsPath;

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { Uri } from 'vscode';
import * as qs from 'querystring';
export interface GitUriParams {
path: string;
@@ -13,25 +12,11 @@ export interface GitUriParams {
}
export function isGitUri(uri: Uri): boolean {
return /^git(fs)?$/.test(uri.scheme);
return /^git$/.test(uri.scheme);
}
export function fromGitUri(uri: Uri): GitUriParams {
const result = qs.parse(uri.query) as any;
if (!result) {
throw new Error('Invalid git URI: empty query');
}
if (typeof result.path !== 'string') {
throw new Error('Invalid git URI: missing path');
}
if (typeof result.ref !== 'string') {
throw new Error('Invalid git URI: missing ref');
}
return result;
return JSON.parse(uri.query);
}
export interface GitUriOptions {
@@ -61,8 +46,8 @@ export function toGitUri(uri: Uri, ref: string, options: GitUriOptions = {}): Ur
}
return uri.with({
scheme: 'gitfs',
scheme: 'git',
path,
query: qs.stringify(params as any)
query: JSON.stringify(params)
});
}

View File

@@ -235,9 +235,9 @@
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit markup.inserted.git-commit",
"r": {
"dark_plus": "markup.inserted: #B5CEA8",
"light_plus": "markup.inserted: #09885A",
"light_plus": "markup.inserted: #098658",
"dark_vs": "markup.inserted: #B5CEA8",
"light_vs": "markup.inserted: #09885A",
"light_vs": "markup.inserted: #098658",
"hc_black": "markup.inserted: #B5CEA8"
}
},
@@ -252,4 +252,4 @@
"hc_black": "comment: #7CA668"
}
}
]
]

View File

@@ -147,9 +147,9 @@
"t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
"r": {
"dark_plus": "markup.inserted: #B5CEA8",
"light_plus": "markup.inserted: #09885A",
"light_plus": "markup.inserted: #098658",
"dark_vs": "markup.inserted: #B5CEA8",
"light_vs": "markup.inserted: #09885A",
"light_vs": "markup.inserted: #098658",
"hc_black": "markup.inserted: #B5CEA8"
}
},
@@ -158,10 +158,10 @@
"t": "source.diff markup.inserted.diff",
"r": {
"dark_plus": "markup.inserted: #B5CEA8",
"light_plus": "markup.inserted: #09885A",
"light_plus": "markup.inserted: #098658",
"dark_vs": "markup.inserted: #B5CEA8",
"light_vs": "markup.inserted: #09885A",
"light_vs": "markup.inserted: #098658",
"hc_black": "markup.inserted: #B5CEA8"
}
}
]
]

View File

@@ -26,9 +26,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -81,9 +81,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -136,9 +136,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -191,9 +191,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -246,9 +246,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -301,9 +301,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -356,9 +356,9 @@
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
"r": {
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
"light_plus": "constant.sha.git-rebase: #09885A",
"light_plus": "constant.sha.git-rebase: #098658",
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
"light_vs": "constant.sha.git-rebase: #09885A",
"light_vs": "constant.sha.git-rebase: #098658",
"hc_black": "constant.sha.git-rebase: #B5CEA8"
}
},
@@ -538,4 +538,4 @@
"hc_black": "comment: #7CA668"
}
}
]
]

View File

@@ -236,7 +236,7 @@ class Preview extends Disposable {
}
private async getResourcePath(webviewEditor: vscode.WebviewPanel, resource: vscode.Uri, version: string): Promise<string> {
if (resource.scheme === 'gitfs') {
if (resource.scheme === 'git') {
const stat = await vscode.workspace.fs.stat(resource);
if (stat.size === 0) {
return this.emptyPngDataUri;

View File

@@ -117,7 +117,8 @@ export function activate(context: ExtensionContext) {
documentSelector,
initializationOptions: {
handledSchemaProtocols: ['file'], // language server only loads file-URI. Fetching schemas with other protocols ('http'...) are made on the client.
provideFormatter: false // tell the server to not provide formatting capability and ignore the `json.format.enable` setting.
provideFormatter: false, // tell the server to not provide formatting capability and ignore the `json.format.enable` setting.
customCapabilities: { rangeFormatting: { editLimit: 1000 } }
},
synchronize: {
// Synchronize the setting section 'json' to the server

View File

@@ -111,12 +111,16 @@
},
"editor.suggest.insertMode": "replace"
}
}
},
"jsonValidation": [{
"fileMatch": "*.schema.json",
"url": "http://json-schema.org/draft-07/schema#"
}]
},
"dependencies": {
"request-light": "^0.2.5",
"vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^6.0.0-next.3",
"vscode-languageclient": "^6.0.1",
"vscode-nls": "^4.1.1"
},
"devDependencies": {

View File

@@ -46,6 +46,8 @@ The client can send the following initialization options to the server:
- `provideFormatter: boolean | undefined`. If defined, the value defines whether the server provides the `documentRangeFormattingProvider` capability on initialization. If undefined, the setting `json.format.enable` is used to determine whether formatting is provided. The formatter will then be registered through dynamic registration. If the client does not support dynamic registration, no formatter will be available.
- `handledSchemaProtocols`: The URI schemas handles by the server. See section `Schema configuration` below.
- `customCapabilities`: Additional non-LSP client capabilities:
- `rangeFormatting: { editLimit: x } }`: For performance reasons, limit the number of edits returned by the range formatter to `x`.
### Settings

View File

@@ -14,8 +14,8 @@
"dependencies": {
"jsonc-parser": "^2.2.0",
"request-light": "^0.2.5",
"vscode-json-languageservice": "^3.4.9",
"vscode-languageserver": "^6.0.0-next.3",
"vscode-json-languageservice": "^3.4.12",
"vscode-languageserver": "^6.0.1",
"vscode-uri": "^2.1.1"
},
"devDependencies": {

View File

@@ -6,7 +6,7 @@
import {
createConnection, IConnection,
TextDocuments, InitializeParams, InitializeResult, NotificationType, RequestType,
DocumentRangeFormattingRequest, Disposable, ServerCapabilities, TextDocumentSyncKind
DocumentRangeFormattingRequest, Disposable, ServerCapabilities, TextDocumentSyncKind, TextEdit
} from 'vscode-languageserver';
import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light';
@@ -16,7 +16,7 @@ import * as URL from 'url';
import { posix } from 'path';
import { setTimeout, clearTimeout } from 'timers';
import { formatError, runSafe, runSafeAsync } from './utils/runner';
import { TextDocument, JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities, SchemaRequestService, Diagnostic } from 'vscode-json-languageservice';
import { TextDocument, JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities, SchemaRequestService, Diagnostic, Range, Position } from 'vscode-json-languageservice';
import { getLanguageModelCache } from './languageModelCache';
interface ISchemaAssociations {
@@ -126,12 +126,13 @@ let hierarchicalDocumentSymbolSupport = false;
let foldingRangeLimitDefault = Number.MAX_VALUE;
let foldingRangeLimit = Number.MAX_VALUE;
let resultLimit = Number.MAX_VALUE;
let formatterMaxNumberOfEdits = Number.MAX_VALUE;
// After the server has started the client sends an initialize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilities.
connection.onInitialize((params: InitializeParams): InitializeResult => {
const handledProtocols = params.initializationOptions && params.initializationOptions['handledSchemaProtocols'];
const handledProtocols = params.initializationOptions?.handledSchemaProtocols;
languageService = getLanguageService({
schemaRequestService: getSchemaRequestService(handledProtocols),
@@ -153,9 +154,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
}
clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false);
dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (typeof params.initializationOptions.provideFormatter !== 'boolean');
dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (typeof params.initializationOptions?.provideFormatter !== 'boolean');
foldingRangeLimitDefault = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE);
hierarchicalDocumentSymbolSupport = getClientCapability('textDocument.documentSymbol.hierarchicalDocumentSymbolSupport', false);
formatterMaxNumberOfEdits = params.initializationOptions?.customCapabilities?.rangeFormatting?.editLimit || Number.MAX_VALUE;
const capabilities: ServerCapabilities = {
textDocumentSync: TextDocumentSyncKind.Incremental,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : undefined,
@@ -445,7 +447,12 @@ connection.onDocumentRangeFormatting((formatParams, token) => {
return runSafe(() => {
const document = documents.get(formatParams.textDocument.uri);
if (document) {
return languageService.format(document, formatParams.range, formatParams.options);
const edits = languageService.format(document, formatParams.range, formatParams.options);
if (edits.length > formatterMaxNumberOfEdits) {
const newText = TextDocument.applyEdits(document, edits);
return [TextEdit.replace(Range.create(Position.create(0, 0), document.positionAt(document.getText().length - 1)), newText)];
}
return edits;
}
return [];
}, [], `Error while formatting range for ${formatParams.textDocument.uri}`, token);

View File

@@ -80,57 +80,52 @@ request-light@^0.2.5:
https-proxy-agent "^2.2.3"
vscode-nls "^4.1.1"
vscode-json-languageservice@^3.4.9:
version "3.4.9"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.9.tgz#7ce485bb0f9a07b4d879c988baac9be2222909ad"
integrity sha512-4VCpZ9ooea/Zc/MTnj1ccc9C7rqcoinKVQLhLoi6jw6yueSf4y4tg/YIUiPPVMlEAG7ZCPS+NVmqxisQ+mOsSw==
vscode-json-languageservice@^3.4.12:
version "3.4.12"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.12.tgz#e7c96a1824896a624cc7bb14f46fbf9cb7e6c5a3"
integrity sha512-+tA0KPVM1pDfORZqsQen7bY5buBpQGDTVYEobm5MoGtXNeZY2Kn0iy5wIQqXveb28LRv/I5xKE87dmNJTEaijQ==
dependencies:
jsonc-parser "^2.2.0"
vscode-languageserver-textdocument "^1.0.0-next.4"
vscode-languageserver-types "^3.15.0-next.6"
vscode-languageserver-textdocument "^1.0.1-next.1"
vscode-languageserver-types "^3.15.0"
vscode-nls "^4.1.1"
vscode-uri "^2.1.0"
vscode-uri "^2.1.1"
vscode-jsonrpc@^5.0.0-next.2:
version "5.0.0-next.2"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-jsonrpc@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz#9bab9c330d89f43fc8c1e8702b5c36e058a01794"
integrity sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==
vscode-languageserver-protocol@^3.15.0-next.10:
version "3.15.0-next.10"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.10.tgz#f1382f0c270ae5d0c2c7e552483285fb75810914"
integrity sha512-TmbBhKrBoYNX+/pQGwoXmy2qlOfjGBUhwUGIzQoWpj8qtDzYuLof8bi19rGLZ9sVuSHh3anvIyVpGJEqT0QODQ==
vscode-languageserver-protocol@^3.15.1:
version "3.15.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.1.tgz#7555e595f0058b9a166f14605ad039e97fab320a"
integrity sha512-wJAo06VM9ZBnRqslplDjfz6Tdive0O7z44yNxBFA3x0/YZkXBIL6I+9rwQ/9Y//0X0eCh12FQrj+KmEXf2L5eA==
dependencies:
vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.6"
vscode-jsonrpc "^5.0.1"
vscode-languageserver-types "3.15.0"
vscode-languageserver-textdocument@^1.0.0-next.4:
version "1.0.0-next.4"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.0-next.4.tgz#8f7afdfe3e81411f57baaa29bb3214d1907160cd"
integrity sha512-LJ5WfoBO54nqinjlLJKnjoo2Im4bIvPJ8bFT7R0C84ZI36iK8M29ddslfe5jUeWNSTtCda7YuKdKsDIq38HpgA==
vscode-languageserver-textdocument@^1.0.1-next.1:
version "1.0.1-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1-next.1.tgz#c8f2f792c7c88d33ea8441ca04bfb8376896b671"
integrity sha512-Cmt0KsNxouns+d7/Kw/jWtWU9Z3h56z1qAA8utjDOEqrDcrTs2rDXv3EJRa99nuKM3wVf6DbWym1VqL9q71XPA==
vscode-languageserver-types@^3.15.0-next.6:
version "3.15.0-next.6"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.6.tgz#7a990d00c39ad4e744335afb4cc422a3e687ff25"
integrity sha512-+4jfvmZ26oFMSX6EgPRB75PWHoT8pzyWuSSWk0erC4hTzmJq2gWxVLh20bZutZjMmiivawvPshtM3XZhX2SttA==
vscode-languageserver-types@3.15.0, vscode-languageserver-types@^3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0.tgz#c45a23308ec0967135c483b759dfaf97978d9e0a"
integrity sha512-AXteNagMhBWnZ6gNN0UB4HTiD/7TajgfHl6jaM6O7qz3zDJw0H3Jf83w05phihnBRCML+K6Ockh8f8bL0OObPw==
vscode-languageserver@^6.0.0-next.3:
version "6.0.0-next.3"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.3.tgz#41e2fda6417939792f6a19fc19ecbb2f080e2072"
integrity sha512-Q6T+KwYuoXV9KRHD6x7RfTU13pV0xAX2BtcuvSC/LBCiVAnEIOe7jKZjzya+B9gDvSk4hpfvhPefy5IdQK1mpQ==
vscode-languageserver@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.1.tgz#4f499d245f1baf83bd607dd79c4c3fd19e8cefc0"
integrity sha512-Wk4I/Dn5KNARWockdCrYuuImJz6bpYG8n2G3Kk5AU6Xy9nWNHD6YjB9/Rd99p4goViZOyETM+hYE81LnEzQZUA==
dependencies:
vscode-languageserver-protocol "^3.15.0-next.10"
vscode-languageserver-protocol "^3.15.1"
vscode-nls@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
vscode-uri@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.0.tgz#475a4269e63edbc13914b40c84bc1416e3398156"
integrity sha512-3voe44nOhb6OdKlpZShVsmVvY2vFQHMe6REP3Ky9RVJuPyM/XidsjH6HncCIDdSmbcF5YQHrTC/Q+Q2loJGkOw==
vscode-uri@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.1.tgz#5aa1803391b6ebdd17d047f51365cf62c38f6e90"

View File

@@ -120,31 +120,31 @@ vscode-extension-telemetry@0.1.1:
dependencies:
applicationinsights "1.0.8"
vscode-jsonrpc@^5.0.0-next.2:
version "5.0.0-next.2"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-jsonrpc@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz#9bab9c330d89f43fc8c1e8702b5c36e058a01794"
integrity sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==
vscode-languageclient@^6.0.0-next.3:
version "6.0.0-next.3"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.3.tgz#41b701d963fc7affc01e9279532a747fcd4f3810"
integrity sha512-SuSaG9xjqkROm4Ie0jQig0CFDuU/WxHERegl3kRsFHDbhMSK4dH45ZeBY5zMWUgZ+LrIrEbwf8qWNlrTRBlUgg==
vscode-languageclient@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.1.tgz#acd138e0a19a40c5788365e882ae11c164d9a460"
integrity sha512-7yZaSHichTJEyOJykI2RLQEECf9MqNLoklzC/1OVi/M8ioIsWQ1+lkN1nTsUhd6+F7p9ar9dNmPiEhL0i5uUBA==
dependencies:
semver "^6.3.0"
vscode-languageserver-protocol "^3.15.0-next.10"
vscode-languageserver-protocol "^3.15.1"
vscode-languageserver-protocol@^3.15.0-next.10:
version "3.15.0-next.10"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.10.tgz#f1382f0c270ae5d0c2c7e552483285fb75810914"
integrity sha512-TmbBhKrBoYNX+/pQGwoXmy2qlOfjGBUhwUGIzQoWpj8qtDzYuLof8bi19rGLZ9sVuSHh3anvIyVpGJEqT0QODQ==
vscode-languageserver-protocol@^3.15.1:
version "3.15.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.1.tgz#7555e595f0058b9a166f14605ad039e97fab320a"
integrity sha512-wJAo06VM9ZBnRqslplDjfz6Tdive0O7z44yNxBFA3x0/YZkXBIL6I+9rwQ/9Y//0X0eCh12FQrj+KmEXf2L5eA==
dependencies:
vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.6"
vscode-jsonrpc "^5.0.1"
vscode-languageserver-types "3.15.0"
vscode-languageserver-types@^3.15.0-next.6:
version "3.15.0-next.6"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.6.tgz#7a990d00c39ad4e744335afb4cc422a3e687ff25"
integrity sha512-+4jfvmZ26oFMSX6EgPRB75PWHoT8pzyWuSSWk0erC4hTzmJq2gWxVLh20bZutZjMmiivawvPshtM3XZhX2SttA==
vscode-languageserver-types@3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0.tgz#c45a23308ec0967135c483b759dfaf97978d9e0a"
integrity sha512-AXteNagMhBWnZ6gNN0UB4HTiD/7TajgfHl6jaM6O7qz3zDJw0H3Jf83w05phihnBRCML+K6Ockh8f8bL0OObPw==
vscode-nls@^4.1.1:
version "4.1.1"

View File

@@ -67,12 +67,6 @@
"scopeName": "source.json.comments",
"path": "./syntaxes/JSONC.tmLanguage.json"
}
],
"jsonValidation": [
{
"fileMatch": "*.schema.json",
"url": "http://json-schema.org/draft-07/schema#"
}
]
}
}

View File

@@ -279,9 +279,9 @@
"t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json constant.numeric.json",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -488,9 +488,9 @@
"t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json constant.numeric.json",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -686,9 +686,9 @@
"t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json constant.numeric.json",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1165,4 +1165,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View File

@@ -950,9 +950,9 @@
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell meta.attribute.powershell constant.numeric.integer.powershell",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1522,9 +1522,9 @@
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell constant.numeric.integer.powershell",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1599,9 +1599,9 @@
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell constant.numeric.integer.powershell",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2892,4 +2892,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View File

@@ -169,9 +169,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -565,9 +565,9 @@
"t": "source.python meta.function-call.python meta.function-call.arguments.python constant.numeric.float.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1137,9 +1137,9 @@
"t": "source.python meta.function.python meta.function.parameters.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1214,9 +1214,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1280,9 +1280,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1324,9 +1324,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1390,9 +1390,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1456,9 +1456,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1522,9 +1522,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1566,9 +1566,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1632,9 +1632,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1698,9 +1698,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1764,9 +1764,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1808,9 +1808,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1874,9 +1874,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1962,9 +1962,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2424,9 +2424,9 @@
"t": "source.python meta.function-call.python meta.function-call.arguments.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2446,9 +2446,9 @@
"t": "source.python meta.function-call.python meta.function-call.arguments.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2468,9 +2468,9 @@
"t": "source.python meta.function-call.python meta.function-call.arguments.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2490,9 +2490,9 @@
"t": "source.python meta.function-call.python meta.function-call.arguments.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -2985,9 +2985,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3359,9 +3359,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3414,9 +3414,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3480,9 +3480,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3568,9 +3568,9 @@
"t": "source.python constant.numeric.float.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3601,9 +3601,9 @@
"t": "source.python constant.numeric.float.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3656,9 +3656,9 @@
"t": "source.python constant.numeric.float.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3722,9 +3722,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3854,9 +3854,9 @@
"t": "source.python constant.numeric.float.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -3898,9 +3898,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -6252,9 +6252,9 @@
"t": "source.python constant.numeric.dec.python",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -6797,4 +6797,4 @@
"hc_black": "string: #CE9178"
}
}
]
]

View File

@@ -554,9 +554,9 @@
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -598,9 +598,9 @@
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -631,9 +631,9 @@
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -675,9 +675,9 @@
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -708,9 +708,9 @@
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1044,4 +1044,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View File

@@ -25,46 +25,6 @@
"editor.lineNumbers": "off"
}
},
"commands": [
{
"command": "searchResult.rerunSearch",
"title": "%searchResult.rerunSearch.title%",
"category": "Search Result",
"icon": {
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
},
{
"command": "searchResult.rerunSearchWithContext",
"title": "%searchResult.rerunSearchWithContext.title%",
"category": "Search Result",
"icon": {
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
}
],
"menus": {
"commandPalette": [
{
"command": "searchResult.rerunSearch",
"when": "false"
},
{
"command": "searchResult.rerunSearchWithContext",
"when": "false"
}
],
"editor/title": [
{
"command": "searchResult.rerunSearch",
"when": "editorLangId == search-result",
"alt": "searchResult.rerunSearchWithContext",
"group": "navigation"
}
]
},
"languages": [
{
"id": "search-result",

View File

@@ -1,6 +1,4 @@
{
"displayName": "Search Result",
"description": "Provides syntax highlighting and language features for tabbed search results.",
"searchResult.rerunSearch.title": "Search Again",
"searchResult.rerunSearchWithContext.title": "Search Again (With Context)"
"description": "Provides syntax highlighting and language features for tabbed search results."
}

View File

@@ -34,8 +34,6 @@ export function activate(context: vscode.ExtensionContext) {
}
context.subscriptions.push(
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch')),
vscode.commands.registerCommand('searchResult.rerunSearchWithContext', () => vscode.commands.executeCommand('search.action.rerunEditorSearchWithContext')),
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {

View File

@@ -136,9 +136,9 @@
"t": "source.sql constant.numeric.sql",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -180,9 +180,9 @@
"t": "source.sql constant.numeric.sql",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -213,9 +213,9 @@
"t": "source.sql constant.numeric.sql",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -268,9 +268,9 @@
"t": "source.sql constant.numeric.sql",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -290,9 +290,9 @@
"t": "source.sql constant.numeric.sql",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -318,4 +318,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View File

@@ -51,7 +51,7 @@
"keyword.operator.minus.exponent"
],
"settings": {
"foreground": "#09885a"
"foreground": "#098658"
}
},
{
@@ -130,7 +130,7 @@
{
"scope": "markup.inserted",
"settings": {
"foreground": "#09885a"
"foreground": "#098658"
}
},
{
@@ -185,7 +185,7 @@
{
"scope": "meta.preprocessor.numeric",
"settings": {
"foreground": "#09885a"
"foreground": "#098658"
}
},
{
@@ -346,7 +346,7 @@
{
"scope": "keyword.other.unit",
"settings": {
"foreground": "#09885a"
"foreground": "#098658"
}
},
{
@@ -367,7 +367,7 @@
{
"scope": "constant.sha.git-rebase",
"settings": {
"foreground": "#09885a"
"foreground": "#098658"
}
},
{

View File

@@ -4,52 +4,131 @@
*--------------------------------------------------------------------------------------------*/
import * as crypto from 'crypto';
import * as vscode from 'vscode';
import * as https from 'https';
import * as querystring from 'querystring';
import { keychain } from './keychain';
import { toBase64UrlEncoding } from './utils';
import * as vscode from 'vscode';
import { createServer, startServer } from './authServer';
import { keychain } from './keychain';
import Logger from './logger';
import { toBase64UrlEncoding } from './utils';
const redirectUrl = 'https://vscode-redirect.azurewebsites.net/';
const loginEndpointUrl = 'https://login.microsoftonline.com/';
const clientId = 'aebc6443-996d-45c2-90f0-388ff96faa56';
const scope = 'https://management.core.windows.net/.default offline_access';
const tenant = 'common';
const tenant = 'organizations';
interface IToken {
expiresIn: string; // How long access token is valid, in seconds
accessToken: string;
refreshToken: string;
displayName: string;
scope: string;
sessionId: string; // The account id + the scope
}
interface ITokenClaims {
tid: string;
email?: string;
unique_name?: string;
oid?: string;
altsecid?: string;
scp: string;
}
interface IStoredSession {
id: string;
refreshToken: string;
scope: string; // Scopes are alphabetized and joined with a space
}
export const onDidChangeSessions = new vscode.EventEmitter<void>();
export class AzureActiveDirectoryService {
private _token: IToken | undefined;
private _refreshTimeout: NodeJS.Timeout | undefined;
private _tokens: IToken[] = [];
private _refreshTimeouts: Map<string, NodeJS.Timeout> = new Map<string, NodeJS.Timeout>();
public async initialize(): Promise<void> {
const existingRefreshToken = await keychain.getToken();
if (existingRefreshToken) {
await this.refreshToken(existingRefreshToken);
const storedData = await keychain.getToken();
if (storedData) {
try {
const sessions = this.parseStoredData(storedData);
const refreshes = sessions.map(async session => {
try {
await this.refreshToken(session.refreshToken, session.scope);
} catch (e) {
await this.logout(session.id);
}
});
await Promise.all(refreshes);
} catch (e) {
await this.clearSessions();
}
}
this.pollForChange();
}
private parseStoredData(data: string): IStoredSession[] {
return JSON.parse(data);
}
private async storeTokenData(): Promise<void> {
const serializedData: IStoredSession[] = this._tokens.map(token => {
return {
id: token.sessionId,
refreshToken: token.refreshToken,
scope: token.scope
};
});
await keychain.setToken(JSON.stringify(serializedData));
}
private pollForChange() {
setTimeout(async () => {
const refreshToken = await keychain.getToken();
// Another window has logged in, generate access token for this instance.
if (refreshToken && !this._token) {
await this.refreshToken(refreshToken);
onDidChangeSessions.fire();
let didChange = false;
const storedData = await keychain.getToken();
if (storedData) {
try {
const sessions = this.parseStoredData(storedData);
let promises = sessions.map(async session => {
const matchesExisting = this._tokens.some(token => token.scope === session.scope && token.sessionId === session.id);
if (!matchesExisting) {
try {
await this.refreshToken(session.refreshToken, session.scope);
didChange = true;
} catch (e) {
await this.logout(session.id);
}
}
});
promises = promises.concat(this._tokens.map(async token => {
const matchesExisting = sessions.some(session => token.scope === session.scope && token.sessionId === session.id);
if (!matchesExisting) {
await this.logout(token.sessionId);
didChange = true;
}
}));
await Promise.all(promises);
} catch (e) {
Logger.error(e.message);
// if data is improperly formatted, remove all of it and send change event
this.clearSessions();
didChange = true;
}
} else {
if (this._tokens.length) {
// Log out all
await this.clearSessions();
didChange = true;
}
}
// Another window has logged out
if (!refreshToken && this._token) {
await this.logout();
if (didChange) {
onDidChangeSessions.fire();
}
@@ -57,31 +136,30 @@ export class AzureActiveDirectoryService {
}, 1000 * 30);
}
private tokenToAccount(token: IToken): vscode.Session {
private convertToSession(token: IToken): vscode.Session {
return {
id: '',
id: token.sessionId,
accessToken: token.accessToken,
displayName: this.getDisplayNameFromToken(token.accessToken)
displayName: token.displayName,
scopes: token.scope.split(' ')
};
}
private getDisplayNameFromToken(accessToken: string): string {
let displayName = 'user@example.com';
private getTokenClaims(accessToken: string): ITokenClaims {
try {
// TODO fixme
displayName = JSON.parse(atob(accessToken.split('.')[1]));
return JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString());
} catch (e) {
// Fall back to example display name
Logger.error(e.message);
throw new Error('Unable to read token claims');
}
return displayName;
}
get sessions(): vscode.Session[] {
return this._token ? [this.tokenToAccount(this._token)] : [];
return this._tokens.map(token => this.convertToSession(token));
}
public async login(): Promise<void> {
public async login(scope: string): Promise<void> {
Logger.info('Logging in...');
const nonce = crypto.randomBytes(16).toString('base64');
const { server, redirectPromise, codePromise } = createServer(nonce);
@@ -118,11 +196,13 @@ export class AzureActiveDirectoryService {
if ('err' in codeRes) {
throw codeRes.err;
}
token = await this.exchangeCodeForToken(codeRes.code, codeVerifier);
this.setToken(token);
token = await this.exchangeCodeForToken(codeRes.code, codeVerifier, scope);
this.setToken(token, scope);
Logger.info('Login successful');
res.writeHead(302, { Location: '/' });
res.end();
} catch (err) {
Logger.error(err.message);
res.writeHead(302, { Location: `/?error=${encodeURIComponent(err && err.message || 'Unknown error')}` });
res.end();
}
@@ -133,28 +213,48 @@ export class AzureActiveDirectoryService {
}
}
private async setToken(token: IToken): Promise<void> {
this._token = token;
if (this._refreshTimeout) {
clearTimeout(this._refreshTimeout);
private async setToken(token: IToken, scope: string): Promise<void> {
const existingToken = this._tokens.findIndex(t => t.sessionId === token.sessionId);
if (existingToken) {
this._tokens.splice(existingToken, 1, token);
} else {
this._tokens.push(token);
}
this._refreshTimeout = setTimeout(async () => {
const existingTimeout = this._refreshTimeouts.get(token.sessionId);
if (existingTimeout) {
clearTimeout(existingTimeout);
}
this._refreshTimeouts.set(token.sessionId, setTimeout(async () => {
try {
await this.refreshToken(token.refreshToken);
await this.refreshToken(token.refreshToken, scope);
} catch (e) {
await this.logout();
await this.logout(token.sessionId);
} finally {
onDidChangeSessions.fire();
}
}, 1000 * (parseInt(token.expiresIn) - 10));
}, 1000 * (parseInt(token.expiresIn) - 10)));
await keychain.setToken(token.refreshToken);
this.storeTokenData();
}
private async exchangeCodeForToken(code: string, codeVerifier: string): Promise<IToken> {
private getTokenFromResponse(buffer: Buffer[], scope: string): IToken {
const json = JSON.parse(Buffer.concat(buffer).toString());
const claims = this.getTokenClaims(json.access_token);
return {
expiresIn: json.expires_in,
accessToken: json.access_token,
refreshToken: json.refresh_token,
scope,
sessionId: claims.tid + (claims.oid || claims.altsecid) + scope,
displayName: claims.email || claims.unique_name || 'user@example.com'
};
}
private async exchangeCodeForToken(code: string, codeVerifier: string, scope: string): Promise<IToken> {
return new Promise((resolve: (value: IToken) => void, reject) => {
Logger.info('Exchanging login code for token');
try {
const postData = querystring.stringify({
grant_type: 'authorization_code',
@@ -182,12 +282,7 @@ export class AzureActiveDirectoryService {
});
result.on('end', () => {
if (result.statusCode === 200) {
const json = JSON.parse(Buffer.concat(buffer).toString());
resolve({
expiresIn: json.expires_in,
accessToken: json.access_token,
refreshToken: json.refresh_token
});
resolve(this.getTokenFromResponse(buffer, scope));
} else {
reject(new Error('Unable to login.'));
}
@@ -202,13 +297,15 @@ export class AzureActiveDirectoryService {
});
} catch (e) {
Logger.error(e.message);
reject(e);
}
});
}
private async refreshToken(refreshToken: string): Promise<IToken> {
private async refreshToken(refreshToken: string, scope: string): Promise<IToken> {
return new Promise((resolve: (value: IToken) => void, reject) => {
Logger.info('Refreshing token...');
const postData = querystring.stringify({
refresh_token: refreshToken,
client_id: clientId,
@@ -231,16 +328,12 @@ export class AzureActiveDirectoryService {
});
result.on('end', async () => {
if (result.statusCode === 200) {
const json = JSON.parse(Buffer.concat(buffer).toString());
const token = {
expiresIn: json.expires_in,
accessToken: json.access_token,
refreshToken: json.refresh_token
};
this.setToken(token);
const token = this.getTokenFromResponse(buffer, scope);
this.setToken(token, scope);
Logger.info('Token refresh success');
resolve(token);
} else {
await this.logout();
Logger.error('Refreshing token failed');
reject(new Error('Refreshing token failed.'));
}
});
@@ -250,16 +343,41 @@ export class AzureActiveDirectoryService {
post.end();
post.on('error', err => {
Logger.error(err.message);
reject(err);
});
});
}
public async logout() {
delete this._token;
await keychain.deleteToken();
if (this._refreshTimeout) {
clearTimeout(this._refreshTimeout);
public async logout(sessionId: string) {
Logger.info(`Logging out of session '${sessionId}'`);
const tokenIndex = this._tokens.findIndex(token => token.sessionId === sessionId);
if (tokenIndex > -1) {
this._tokens.splice(tokenIndex, 1);
}
if (this._tokens.length === 0) {
await keychain.deleteToken();
} else {
this.storeTokenData();
}
const timeout = this._refreshTimeouts.get(sessionId);
if (timeout) {
clearTimeout(timeout);
this._refreshTimeouts.delete(sessionId);
}
}
public async clearSessions() {
Logger.info('Logging out of all sessions');
this._tokens = [];
await keychain.deleteToken();
this._refreshTimeouts.forEach(timeout => {
clearTimeout(timeout);
});
this._refreshTimeouts.clear();
}
}

View File

@@ -14,12 +14,12 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.authentication.registerAuthenticationProvider({
id: 'MSA',
displayName: 'Microsoft Account', // TODO localize
displayName: 'Microsoft',
onDidChangeSessions: onDidChangeSessions.event,
getSessions: () => Promise.resolve(loginService.sessions),
login: async () => {
login: async (scopes: string[]) => {
try {
await loginService.login();
await loginService.login(scopes.sort().join(' '));
return loginService.sessions[0]!;
} catch (e) {
vscode.window.showErrorMessage(`Logging in failed: ${e}`);
@@ -27,7 +27,7 @@ export async function activate(context: vscode.ExtensionContext) {
}
},
logout: async (id: string) => {
return loginService.logout();
return loginService.logout(id);
}
});

View File

@@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
type LogLevel = 'Trace' | 'Info' | 'Error';
class Log {
private output: vscode.OutputChannel;
constructor() {
this.output = vscode.window.createOutputChannel('Account');
}
private data2String(data: any): string {
if (data instanceof Error) {
return data.stack || data.message;
}
if (data.success === false && data.message) {
return data.message;
}
return data.toString();
}
public info(message: string, data?: any): void {
this.logLevel('Info', message, data);
}
public error(message: string, data?: any): void {
this.logLevel('Error', message, data);
}
public logLevel(level: LogLevel, message: string, data?: any): void {
this.output.appendLine(`[${level} - ${this.now()}] ${message}`);
if (data) {
this.output.appendLine(this.data2String(data));
}
}
private now(): string {
const now = new Date();
return padLeft(now.getUTCHours() + '', 2, '0')
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
}
}
function padLeft(s: string, n: number, pad = ' ') {
return pad.repeat(Math.max(0, n - s.length)) + s;
}
const Logger = new Log();
export default Logger;

View File

@@ -20,6 +20,7 @@ declare module 'vscode' {
id: string;
accessToken: string;
displayName: string;
scopes: string[]
}
export interface AuthenticationProvider {
@@ -35,7 +36,7 @@ declare module 'vscode' {
/**
* Prompts a user to login.
*/
login(): Promise<Session>;
login(scopes: string[]): Promise<Session>;
logout(sessionId: string): Promise<void>;
}
@@ -48,13 +49,7 @@ declare module 'vscode' {
export const onDidRegisterAuthenticationProvider: Event<string>;
export const onDidUnregisterAuthenticationProvider: Event<string>;
/**
* Fires with the provider id that changed sessions.
*/
export const onDidChangeSessions: Event<string>;
export function login(providerId: string): Promise<Session>;
export function logout(providerId: string, accountId: string): Promise<void>;
export function getSessions(providerId: string): Promise<ReadonlyArray<Session> | undefined>;
export const providers: ReadonlyArray<AuthenticationProvider>;
}
// #region Ben - extension auth flow (desktop+web)

View File

@@ -257,10 +257,10 @@
"t": "source.yaml constant.numeric.integer.yaml",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
}
]
]

View File

@@ -246,9 +246,9 @@
"t": "source.yaml constant.numeric.float.yaml",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -774,9 +774,9 @@
"t": "source.yaml meta.flow-mapping.yaml meta.flow-pair.yaml meta.flow-pair.value.yaml constant.numeric.integer.yaml",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -906,9 +906,9 @@
"t": "source.yaml constant.numeric.integer.yaml",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"light_plus": "constant.numeric: #098658",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"light_vs": "constant.numeric: #098658",
"hc_black": "constant.numeric: #B5CEA8"
}
},
@@ -1132,4 +1132,4 @@
"hc_black": "string: #CE9178"
}
}
]
]

View File

@@ -118,7 +118,7 @@
"coveralls": "^2.11.11",
"cson-parser": "^1.3.3",
"debounce": "^1.0.0",
"electron": "7.1.7",
"electron": "6.1.6",
"eslint": "6.8.0",
"eslint-plugin-jsdoc": "^19.1.0",
"event-stream": "3.3.4",

View File

@@ -95,7 +95,7 @@ class MainThreadNotebookEditor extends Disposable {
}
public save(): Thenable<boolean> {
return this.textFileService.save(this.uri);
return this.textFileService.save(this.uri).then(uri => !!uri);
}
public matches(input: NotebookInput): boolean {
@@ -351,7 +351,7 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
let uriString = URI.revive(uri).toString();
let editor = this._notebookEditors.get(uriString);
if (editor) {
return editor.save();
return editor.save().then(uri => !!uri);
} else {
return Promise.resolve(false);
}

View File

@@ -34,6 +34,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IViewDescriptorService } from 'vs/workbench/common/views';
export class CategoryView extends ViewPane {
@@ -45,9 +46,10 @@ export class CategoryView extends ViewPane {
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
@IInstantiationService instantiationService: IInstantiationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
}
// we want a fixed size, so when we render to will measure our content and set that to be our

View File

@@ -6,7 +6,7 @@
import * as azdata from 'azdata';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { EditorInput, EditorModel } from 'vs/workbench/common/editor';
import { EditorInput, EditorModel, IEditorInput } from 'vs/workbench/common/editor';
import * as DOM from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -139,8 +139,8 @@ export class ModelViewInput extends EditorInput {
/**
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/
save(): Promise<boolean> {
return this._model.save();
save(): Promise<IEditorInput | undefined> {
return this._model.save().then(saved => saved ? this : undefined);
}
public dispose(): void {

View File

@@ -196,7 +196,7 @@ export class QueryTextEditor extends BaseTextEditor {
this.refreshEditorConfiguration();
}
private refreshEditorConfiguration(configuration = this.configurationService.getValue<IEditorConfiguration>(this.getResource())): void {
private refreshEditorConfiguration(configuration = this.textResourceConfigurationService.getValue<IEditorConfiguration>(this.input.getResource())): void {
if (!this.getControl()) {
return;
}

View File

@@ -12,7 +12,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { ContextAwareMenuEntryActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, IViewsRegistry, ViewContainer, ITreeItemLabel, Extensions } from 'vs/workbench/common/views';
import { TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, IViewsRegistry, ViewContainer, ITreeItemLabel, Extensions, IViewDescriptorService } from 'vs/workbench/common/views';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -27,7 +27,7 @@ import { URI } from 'vs/base/common/uri';
import { dirname, basename } from 'vs/base/common/resources';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { FileKind } from 'vs/platform/files/common/files';
import { WorkbenchAsyncDataTree, TreeResourceNavigator2 } from 'vs/platform/list/browser/listService';
import { WorkbenchAsyncDataTree, TreeResourceNavigator } from 'vs/platform/list/browser/listService';
import { localize } from 'vs/nls';
import { timeout } from 'vs/base/common/async';
import { editorFindMatchHighlight, editorFindMatchHighlightBorder, textLinkForeground, textCodeBlockBackground, focusBorder } from 'vs/platform/theme/common/colorRegistry';
@@ -62,9 +62,10 @@ export class CustomTreeViewPanel extends ViewPane {
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
@IInstantiationService instantiationService: IInstantiationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
this.treeView = treeView as ITreeView;
this._register(this.treeView.onDidChangeActions(() => this.updateActions(), this));
@@ -443,7 +444,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
}));
this.tree.setInput(this.root).then(() => this.updateContentAreas());
const customTreeNavigator = new TreeResourceNavigator2(this.tree);
const customTreeNavigator = new TreeResourceNavigator(this.tree);
this._register(customTreeNavigator);
this._register(customTreeNavigator.onDidOpenResource(e => {
if (!e.browserEvent) {

View File

@@ -36,6 +36,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IViewDescriptorService } from 'vs/workbench/common/views';
class AccountPanel extends ViewPane {
public index: number;
@@ -48,9 +49,10 @@ class AccountPanel extends ViewPane {
@IConfigurationService configurationService: IConfigurationService,
@IThemeService private themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
@IInstantiationService instantiationService: IInstantiationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
}
protected renderBody(container: HTMLElement): void {
@@ -126,6 +128,7 @@ export class AccountDialog extends Modal {
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService,
@ILogService logService: ILogService,
@IViewDescriptorService private viewDescriptorService: IViewDescriptorService,
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService
) {
super(
@@ -296,7 +299,8 @@ export class AccountDialog extends Modal {
this._configurationService,
this._themeService,
this.contextKeyService,
this._instantiationService
this._instantiationService,
this.viewDescriptorService
);
attachPanelStyler(providerView, this._themeService);

View File

@@ -86,7 +86,7 @@ function createInstantiationService(addAccountFailureEmitter?: Emitter<string>):
.returns(() => undefined);
// Create a mock account dialog
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!);
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!);
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog);
mockAccountDialog.setup(x => x.onAddAccountErrorEvent)
.returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; });

View File

@@ -393,7 +393,7 @@ suite('commandLineService tests', () => {
querymodelService.setup(c => c.onRunQueryComplete).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let uri = URI.file(args._[0]);
const untitledEditorInput = new UntitledTextEditorInput(uri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
const untitledEditorInput = new UntitledTextEditorInput(uri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
const queryInput = new UntitledQueryEditorInput(undefined, untitledEditorInput, undefined, connectionManagementService.object, querymodelService.object, configurationService.object, undefined);
queryInput.state.connected = true;
const editorService: TypeMoq.Mock<IEditorService> = TypeMoq.Mock.ofType<IEditorService>(TestEditorService, TypeMoq.MockBehavior.Strict);

View File

@@ -20,6 +20,7 @@ import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/br
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ITree } from 'vs/base/parts/tree/browser/tree';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IViewDescriptorService } from 'vs/workbench/common/views';
export class ConnectionViewletPanel extends ViewPane {
@@ -38,9 +39,10 @@ export class ConnectionViewletPanel extends ViewPane {
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@IObjectExplorerService private readonly objectExplorerService: IObjectExplorerService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
) {
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
this._addServerAction = this.instantiationService.createInstance(AddServerAction,
AddServerAction.ID,
AddServerAction.LABEL);

View File

@@ -17,7 +17,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { ConnectionViewletPanel } from 'sql/workbench/contrib/dataExplorer/browser/connectionViewletPanel';
import { Extensions as ViewContainerExtensions, IViewDescriptor, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views';
import { Extensions as ViewContainerExtensions, IViewDescriptor, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -103,9 +103,10 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer {
@IExtensionService extensionService: IExtensionService,
@IConfigurationService configurationService: IConfigurationService,
@IMenuService private menuService: IMenuService,
@IContextKeyService private contextKeyService: IContextKeyService
@IContextKeyService private contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService);
super(VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
}
create(parent: HTMLElement): void {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorInput, EditorModel, EncodingMode } from 'vs/workbench/common/editor';
import { EditorInput, EditorModel, EncodingMode, IEditorInput } from 'vs/workbench/common/editor';
import { IConnectionManagementService, IConnectableInput, INewConnectionParams } from 'sql/platform/connection/common/connectionManagement';
import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { Event, Emitter } from 'vs/base/common/event';
@@ -107,7 +107,7 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
public get objectType(): string { return this._objectType; }
public showResultsEditor(): void { this._showResultsEditor.fire(undefined); }
public isDirty(): boolean { return false; }
public save(): Promise<boolean> { return Promise.resolve(false); }
public save(): Promise<IEditorInput | undefined> { return Promise.resolve(undefined); }
public getTypeId(): string { return EditDataInput.ID; }
public setBootstrappedTrue(): void { this._hasBootstrapped = true; }
public getResource(): URI { return this._uri; }
@@ -220,7 +220,6 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; }
public resolve(refresh?: boolean): Promise<EditorModel> { return this._sql.resolve(); }
public getEncoding(): string { return this._sql.getEncoding(); }
public suggestFileName(): string { return this._sql.suggestFileName(); }
public getName(): string { return this._sql.getName(); }
public get hasAssociatedFilePath(): boolean { return this._sql.hasAssociatedFilePath; }

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorInput, EditorModel } from 'vs/workbench/common/editor';
import { EditorInput, EditorModel, IRevertOptions, GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
import { Emitter, Event } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources';
@@ -230,8 +230,8 @@ export abstract class NotebookInput extends EditorInput {
return this._textInput;
}
public revert(): Promise<boolean> {
return this._textInput.revert();
public revert(group: GroupIdentifier, options?: IRevertOptions): Promise<boolean> {
return this._textInput.revert(group, options);
}
public get notebookUri(): URI {
@@ -283,11 +283,11 @@ export abstract class NotebookInput extends EditorInput {
return this._standardKernels;
}
save(groupId: number, options?: ITextFileSaveOptions): Promise<boolean> {
save(groupId: number, options?: ITextFileSaveOptions): Promise<IEditorInput | undefined> {
return this.textInput.save(groupId, options);
}
saveAs(group: number, options?: ITextFileSaveOptions): Promise<boolean> {
saveAs(group: number, options?: ITextFileSaveOptions): Promise<IEditorInput | undefined> {
return this.textInput.saveAs(group, options);
}

View File

@@ -48,7 +48,7 @@ suite('Notebook Input', function (): void {
let untitledNotebookInput: UntitledNotebookInput;
setup(() => {
untitledTextInput = new UntitledTextEditorInput(untitledUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
untitledTextInput = new UntitledTextEditorInput(untitledUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
untitledNotebookInput = new UntitledNotebookInput(
testTitle, untitledUri, untitledTextInput,
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object);
@@ -169,7 +169,7 @@ suite('Notebook Input', function (): void {
assert.ok(untitledNotebookInput.matches(untitledNotebookInput), 'Input should match itself.');
let otherTestUri = URI.from({ scheme: Schemas.untitled, path: 'OtherTestPath' });
let otherTextInput = new UntitledTextEditorInput(otherTestUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let otherTextInput = new UntitledTextEditorInput(otherTestUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
let otherInput = instantiationService.createInstance(UntitledNotebookInput, 'OtherTestInput', otherTestUri, otherTextInput);
assert.strictEqual(untitledNotebookInput.matches(otherInput), false, 'Input should not match different input.');

View File

@@ -109,6 +109,9 @@ suite('SQL Connection Tree Action tests', () => {
});
const viewsService = new class implements IViewsService {
getActiveViewWithId(id: string): IView {
throw new Error('Method not implemented.');
}
_serviceBrand: undefined;
openView(id: string, focus?: boolean): Promise<IView> {
return Promise.resolve({

View File

@@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { EditorInput } from 'vs/workbench/common/editor';
import { EditorInput, GroupIdentifier, IRevertOptions, ISaveOptions, IEditorInput } from 'vs/workbench/common/editor';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
@@ -17,7 +17,6 @@ import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { ISelectionData, ExecutionPlanOptions } from 'azdata';
import { startsWith } from 'vs/base/common/strings';
import { ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
const MAX_SIZE = 13;
@@ -175,7 +174,9 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab
// Description is shown beside the tab name in the combobox of open editors
public getDescription(): string { return this._description; }
public supportsSplitEditor(): boolean { return false; }
public revert(): Promise<boolean> { return this._text.revert(); }
public revert(group: GroupIdentifier, options?: IRevertOptions): Promise<boolean> {
return this._text.revert(group, options);
}
public isReadonly(): boolean {
return false;
@@ -224,11 +225,11 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab
}
}
save(groupId: number, options?: ITextFileSaveOptions): Promise<boolean> {
return this.text.save(groupId, options);
save(group: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
return this.text.save(group, options);
}
saveAs(group: number, options?: ITextFileSaveOptions): Promise<boolean> {
saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
return this.text.saveAs(group, options);
}

View File

@@ -47,10 +47,6 @@ export class UntitledQueryEditorInput extends QueryEditorInput implements IEncod
return this.text.hasAssociatedFilePath;
}
public suggestFileName(): string {
return this.text.suggestFileName();
}
public setMode(mode: string): void {
this.text.setMode(mode);
}
@@ -75,12 +71,4 @@ export class UntitledQueryEditorInput extends QueryEditorInput implements IEncod
// Subclasses need to explicitly opt-in to being untitled.
return true;
}
hasBackup(): boolean {
if (this.text) {
return this.text.hasBackup();
}
return false;
}
}

View File

@@ -70,7 +70,7 @@ suite('SQL QueryAction Tests', () => {
connectionManagementService = TypeMoq.Mock.ofType<TestConnectionManagementService>(TestConnectionManagementService);
connectionManagementService.setup(q => q.onDisconnect).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
// Setup a reusable mock QueryInput
testQueryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
testQueryInput.setup(x => x.uri).returns(() => testUri);
@@ -175,7 +175,7 @@ suite('SQL QueryAction Tests', () => {
queryModelService.setup(x => x.onRunQueryStart).returns(() => Event.None);
queryModelService.setup(x => x.onRunQueryComplete).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
// ... Mock "isSelectionEmpty" in QueryEditor
let queryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
@@ -224,7 +224,7 @@ suite('SQL QueryAction Tests', () => {
// ... Mock "getSelection" in QueryEditor
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined);
let queryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Loose, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
queryInput.setup(x => x.uri).returns(() => testUri);

View File

@@ -285,7 +285,7 @@ suite('SQL QueryEditor Tests', () => {
return new RunQueryAction(undefined, undefined, undefined);
});
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, new LabelService(undefined, undefined), undefined, undefined);
queryModelService = TypeMoq.Mock.ofType(TestQueryModelService, TypeMoq.MockBehavior.Strict);
queryModelService.setup(x => x.disposeQuery(TypeMoq.It.isAny()));
queryModelService.setup(x => x.onRunQueryComplete).returns(() => Event.None);

View File

@@ -43,6 +43,7 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IViewDescriptorService } from 'vs/workbench/common/views';
const labelDisplay = nls.localize("insights.item", "Item");
const valueDisplay = nls.localize("insights.value", "Value");
@@ -63,9 +64,10 @@ class InsightTableView<T> extends ViewPane {
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
@IInstantiationService instantiationService: IInstantiationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
}
protected renderBody(container: HTMLElement): void {

View File

@@ -25,6 +25,7 @@ import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
class TestEnvironmentService implements IWorkbenchEnvironmentService {
userDataSyncHome: URI;
keybindingsSyncPreviewResource: URI;
argvResource: URI;
userDataSyncLogResource: URI;

View File

@@ -287,7 +287,7 @@ export function addDisposableGenericMouseUpListner(node: EventTarget, handler: (
export function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
return addDisposableListener(node, 'mouseout', (e: MouseEvent) => {
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
let toElement: Node | null = <Node>(e.relatedTarget || e.target);
let toElement: Node | null = <Node>(e.relatedTarget);
while (toElement && toElement !== node) {
toElement = toElement.parentNode;
}
@@ -302,7 +302,7 @@ export function addDisposableNonBubblingMouseOutListener(node: Element, handler:
export function addDisposableNonBubblingPointerOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
return addDisposableListener(node, 'pointerout', (e: MouseEvent) => {
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
let toElement: Node | null = <Node>(e.relatedTarget || e.target);
let toElement: Node | null = <Node>(e.relatedTarget);
while (toElement && toElement !== node) {
toElement = toElement.parentNode;
}
@@ -628,11 +628,17 @@ export function getTopLeftOffset(element: HTMLElement): { left: number; top: num
// Adapted from WinJS.Utilities.getPosition
// and added borders to the mix
let offsetParent = element.offsetParent, top = element.offsetTop, left = element.offsetLeft;
let offsetParent = element.offsetParent;
let top = element.offsetTop;
let left = element.offsetLeft;
while ((element = <HTMLElement>element.parentNode) !== null && element !== document.body && element !== document.documentElement) {
while (
(element = <HTMLElement>element.parentNode) !== null
&& element !== document.body
&& element !== document.documentElement
) {
top -= element.scrollTop;
let c = getComputedStyle(element);
const c = isShadowRoot(element) ? null : getComputedStyle(element);
if (c) {
left -= c.direction !== 'rtl' ? element.scrollLeft : -element.scrollLeft;
}
@@ -793,7 +799,7 @@ export function isAncestor(testChild: Node | null, testAncestor: Node | null): b
}
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
while (node) {
while (node && node.nodeType === node.ELEMENT_NODE) {
if (hasClass(node, clazz)) {
return node;
}
@@ -820,6 +826,27 @@ export function hasParentWithClass(node: HTMLElement, clazz: string, stopAtClazz
return !!findParentWithClass(node, clazz, stopAtClazzOrNode);
}
export function isShadowRoot(node: Node): node is ShadowRoot {
return (
node && !!(<ShadowRoot>node).host && !!(<ShadowRoot>node).mode
);
}
export function isInShadowDOM(domNode: Node): boolean {
return !!getShadowRoot(domNode);
}
export function getShadowRoot(domNode: Node): ShadowRoot | null {
while (domNode.parentNode) {
if (domNode === document.body) {
// reached the body
return null;
}
domNode = domNode.parentNode;
}
return isShadowRoot(domNode) ? domNode : null;
}
export function createStyleSheet(container: HTMLElement = document.getElementsByTagName('head')[0]): HTMLStyleElement {
let style = document.createElement('style');
style.type = 'text/css';
@@ -1167,7 +1194,7 @@ export function hide(...elements: HTMLElement[]): void {
}
function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
while (node) {
while (node && node.nodeType === node.ELEMENT_NODE) {
if (node instanceof HTMLElement && node.hasAttribute(attribute)) {
return node;
}

View File

@@ -25,6 +25,7 @@ export class FastDomNode<T extends HTMLElement> {
private _display: string;
private _position: string;
private _visibility: string;
private _backgroundColor: string;
private _layerHint: boolean;
private _contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint';
@@ -47,6 +48,7 @@ export class FastDomNode<T extends HTMLElement> {
this._display = '';
this._position = '';
this._visibility = '';
this._backgroundColor = '';
this._layerHint = false;
this._contain = 'none';
}
@@ -200,6 +202,14 @@ export class FastDomNode<T extends HTMLElement> {
this.domNode.style.visibility = this._visibility;
}
public setBackgroundColor(backgroundColor: string): void {
if (this._backgroundColor === backgroundColor) {
return;
}
this._backgroundColor = backgroundColor;
this.domNode.style.backgroundColor = this._backgroundColor;
}
public setLayerHinting(layerHint: boolean): void {
if (this._layerHint === layerHint) {
return;

View File

@@ -75,6 +75,7 @@ export class GlobalMouseMoveMonitor<R extends { buttons: number; }> implements I
}
public startMonitoring(
initialElement: HTMLElement,
initialButtons: number,
mouseMoveEventMerger: IEventMerger<R>,
mouseMoveCallback: IMouseMoveCallback<R>,
@@ -88,11 +89,18 @@ export class GlobalMouseMoveMonitor<R extends { buttons: number; }> implements I
this._mouseMoveCallback = mouseMoveCallback;
this._onStopCallback = onStopCallback;
let windowChain = IframeUtils.getSameOriginWindowChain();
const windowChain = IframeUtils.getSameOriginWindowChain();
const mouseMove = platform.isIOS && BrowserFeatures.pointerEvents ? 'pointermove' : 'mousemove';
const mouseUp = platform.isIOS && BrowserFeatures.pointerEvents ? 'pointerup' : 'mouseup';
for (const element of windowChain) {
this._hooks.add(dom.addDisposableThrottledListener(element.window.document, mouseMove,
const listenTo: (Document | ShadowRoot)[] = windowChain.map(element => element.window.document);
const shadowRoot = dom.getShadowRoot(initialElement);
if (shadowRoot) {
listenTo.unshift(shadowRoot);
}
for (const element of listenTo) {
this._hooks.add(dom.addDisposableThrottledListener(element, mouseMove,
(data: R) => {
if (data.buttons !== initialButtons) {
// Buttons state has changed in the meantime
@@ -103,7 +111,7 @@ export class GlobalMouseMoveMonitor<R extends { buttons: number; }> implements I
},
(lastEvent: R | null, currentEvent) => this._mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)
));
this._hooks.add(dom.addDisposableListener(element.window.document, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));
this._hooks.add(dom.addDisposableListener(element, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));
}
if (IframeUtils.hasDifferentOriginAncestor()) {

View File

@@ -5,7 +5,7 @@
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?ed926e87ee4e27771159d875e877f74a") format("truetype");
src: url("./codicon.ttf?be537a78617db0869caa4b4cc683a24a") format("truetype");
}
.codicon[class*='codicon-'] {
@@ -119,6 +119,7 @@
.codicon-github:before { content: "\ea84" }
.codicon-terminal:before { content: "\ea85" }
.codicon-console:before { content: "\ea85" }
.codicon-repl:before { content: "\ea85" }
.codicon-zap:before { content: "\ea86" }
.codicon-symbol-event:before { content: "\ea86" }
.codicon-error:before { content: "\ea87" }
@@ -410,4 +411,6 @@
.codicon-menu:before { content: "\eb94" }
.codicon-expand-all:before { content: "\eb95" }
.codicon-feedback:before { content: "\eb96" }
.codicon-group-by-ref-type:before { content: "\eb97" }
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
.codicon-debug-alt:before { content: "\f101" }

View File

@@ -92,8 +92,10 @@ class FastLabelNode {
export class IconLabel extends Disposable {
private domNode: FastLabelNode;
private descriptionContainer: FastLabelNode;
private nameNode: Label | LabelWithHighlights;
private descriptionContainer: FastLabelNode;
private descriptionNode: FastLabelNode | HighlightedLabel | undefined;
private descriptionNodeFactory: () => FastLabelNode | HighlightedLabel;

View File

@@ -844,7 +844,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
// sanitize feedback list
feedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort();
feedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort((a, b) => a - b);
feedback = feedback[0] === -1 ? [-1] : feedback;
if (equalsDragFeedback(this.currentDragFeedback, feedback)) {

View File

@@ -61,6 +61,7 @@ export abstract class AbstractScrollbar extends Widget {
this._scrollable = opts.scrollable;
this._scrollbarState = opts.scrollbarState;
this._visibilityController = this._register(new ScrollbarVisibilityController(opts.visibility, 'visible scrollbar ' + opts.extraScrollbarClassName, 'invisible scrollbar ' + opts.extraScrollbarClassName));
this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());
this._mouseMoveMonitor = this._register(new GlobalMouseMoveMonitor<IStandardMouseMoveEventData>());
this._shouldRender = true;
this.domNode = createFastDomNode(document.createElement('div'));
@@ -216,13 +217,14 @@ export abstract class AbstractScrollbar extends Widget {
}
}
private _sliderMouseDown(e: ISimplifiedMouseEvent, onDragFinished: () => void): void {
private _sliderMouseDown(e: IMouseEvent, onDragFinished: () => void): void {
const initialMousePosition = this._sliderMousePosition(e);
const initialMouseOrthogonalPosition = this._sliderOrthogonalMousePosition(e);
const initialScrollbarState = this._scrollbarState.clone();
this.slider.toggleClassName('active', true);
this._mouseMoveMonitor.startMonitoring(
e.target,
e.buttons,
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {

View File

@@ -13,13 +13,18 @@ import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from
export class HorizontalScrollbar extends AbstractScrollbar {
constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) {
const scrollDimensions = scrollable.getScrollDimensions();
const scrollPosition = scrollable.getCurrentScrollPosition();
super({
lazyRender: options.lazyRender,
host: host,
scrollbarState: new ScrollbarState(
(options.horizontalHasArrows ? options.arrowSize : 0),
(options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize),
(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize)
(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize),
scrollDimensions.width,
scrollDimensions.scrollWidth,
scrollPosition.scrollLeft
),
visibility: options.horizontal,
extraScrollbarClassName: 'horizontal',

View File

@@ -93,6 +93,7 @@ export class ScrollbarArrow extends Widget {
this._mousedownScheduleRepeatTimer.cancelAndSet(scheduleRepeater, 200);
this._mouseMoveMonitor.startMonitoring(
e.target,
e.buttons,
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {

View File

@@ -62,14 +62,14 @@ export class ScrollbarState {
private _computedSliderRatio: number;
private _computedSliderPosition: number;
constructor(arrowSize: number, scrollbarSize: number, oppositeScrollbarSize: number) {
constructor(arrowSize: number, scrollbarSize: number, oppositeScrollbarSize: number, visibleSize: number, scrollSize: number, scrollPosition: number) {
this._scrollbarSize = Math.round(scrollbarSize);
this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize);
this._arrowSize = Math.round(arrowSize);
this._visibleSize = 0;
this._scrollSize = 0;
this._scrollPosition = 0;
this._visibleSize = visibleSize;
this._scrollSize = scrollSize;
this._scrollPosition = scrollPosition;
this._computedAvailableSize = 0;
this._computedIsNeeded = false;
@@ -81,11 +81,7 @@ export class ScrollbarState {
}
public clone(): ScrollbarState {
let r = new ScrollbarState(this._arrowSize, this._scrollbarSize, this._oppositeScrollbarSize);
r.setVisibleSize(this._visibleSize);
r.setScrollSize(this._scrollSize);
r.setScrollPosition(this._scrollPosition);
return r;
return new ScrollbarState(this._arrowSize, this._scrollbarSize, this._oppositeScrollbarSize, this._visibleSize, this._scrollSize, this._scrollPosition);
}
public setVisibleSize(visibleSize: number): boolean {

View File

@@ -13,6 +13,8 @@ import { INewScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from
export class VerticalScrollbar extends AbstractScrollbar {
constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) {
const scrollDimensions = scrollable.getScrollDimensions();
const scrollPosition = scrollable.getCurrentScrollPosition();
super({
lazyRender: options.lazyRender,
host: host,
@@ -20,7 +22,10 @@ export class VerticalScrollbar extends AbstractScrollbar {
(options.verticalHasArrows ? options.arrowSize : 0),
(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize),
// give priority to vertical scroll bar over horizontal and let it scroll all the way to the bottom
0
0,
scrollDimensions.height,
scrollDimensions.scrollHeight,
scrollPosition.scrollTop
),
visibility: options.vertical,
extraScrollbarClassName: 'vertical',

View File

@@ -6,7 +6,11 @@
import { URI } from 'vs/base/common/uri';
export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string {
return URI.parse(requirefn.toUrl(relativePath)).fsPath;
return getUriFromAmdModule(requirefn, relativePath).fsPath;
}
export function getUriFromAmdModule(requirefn: typeof require, relativePath: string): URI {
return URI.parse(requirefn.toUrl(relativePath));
}
/**

View File

@@ -481,8 +481,9 @@ export class Queue<T> extends Limiter<T> {
* A helper to organize queues per resource. The ResourceQueue makes sure to manage queues per resource
* by disposing them once the queue is empty.
*/
export class ResourceQueue {
private queues: Map<string, Queue<void>> = new Map();
export class ResourceQueue implements IDisposable {
private readonly queues = new Map<string, Queue<void>>();
queueFor(resource: URI): Queue<void> {
const key = resource.toString();
@@ -498,6 +499,11 @@ export class ResourceQueue {
return this.queues.get(key)!;
}
dispose(): void {
this.queues.forEach(queue => queue.dispose());
this.queues.clear();
}
}
export class TimeoutTimer implements IDisposable {

View File

@@ -148,6 +148,7 @@ export namespace Event {
if (leading && !handle) {
emitter.fire(output);
output = undefined;
}
clearTimeout(handle);

View File

@@ -120,7 +120,7 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo
}
}
function withFormatting(text: string, edit: Edit, formattingOptions: FormattingOptions): Edit[] {
export function withFormatting(text: string, edit: Edit, formattingOptions: FormattingOptions): Edit[] {
// apply the edit
let newText = applyEdit(text, edit);

View File

@@ -228,7 +228,7 @@ function computeIndentLevel(content: string, options: FormattingOptions): number
return Math.floor(nChars / tabSize);
}
function getEOL(options: FormattingOptions, text: string): string {
export function getEOL(options: FormattingOptions, text: string): string {
for (let i = 0; i < text.length; i++) {
const ch = text.charAt(i);
if (ch === '\r') {
@@ -245,4 +245,4 @@ function getEOL(options: FormattingOptions, text: string): string {
export function isEOL(text: string, offset: number) {
return '\r\n'.indexOf(text.charAt(offset)) !== -1;
}
}

View File

@@ -72,6 +72,49 @@ function doFindFreePort(startPort: number, giveUpAfter: number, clb: (port: numb
client.connect(startPort, '127.0.0.1');
}
/**
* Uses listen instead of connect. Is faster, but if there is another listener on 0.0.0.0 then this will take 127.0.0.1 from that listener.
*/
export function findFreePortFaster(startPort: number, giveUpAfter: number, timeout: number): Promise<number> {
let resolved: boolean = false;
let timeoutHandle: NodeJS.Timeout | undefined = undefined;
let countTried: number = 1;
const server = net.createServer({ pauseOnConnect: true });
function doResolve(port: number, resolve: (port: number) => void) {
if (!resolved) {
resolved = true;
server.removeAllListeners();
server.close();
if (timeoutHandle) {
clearTimeout(timeoutHandle);
}
resolve(port);
}
}
return new Promise<number>(resolve => {
timeoutHandle = setTimeout(() => {
doResolve(0, resolve);
}, timeout);
server.on('listening', () => {
doResolve(startPort, resolve);
});
server.on('error', err => {
if (err && ((<any>err).code === 'EADDRINUSE' || (<any>err).code === 'EACCES') && (countTried < giveUpAfter)) {
startPort++;
countTried++;
server.listen(startPort, '127.0.0.1');
} else {
doResolve(0, resolve);
}
});
server.on('close', () => {
doResolve(0, resolve);
});
server.listen(startPort, '127.0.0.1');
});
}
function dispose(socket: net.Socket): void {
try {
socket.removeAllListeners('connect');

File diff suppressed because one or more lines are too long

View File

@@ -8,10 +8,7 @@ import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';
suite('ScrollbarState', () => {
test('inflates slider size', () => {
let actual = new ScrollbarState(0, 14, 0);
actual.setVisibleSize(339);
actual.setScrollSize(42423);
actual.setScrollPosition(32787);
let actual = new ScrollbarState(0, 14, 0, 339, 42423, 32787);
assert.equal(actual.getArrowSize(), 0);
assert.equal(actual.getScrollPosition(), 32787);
@@ -34,10 +31,7 @@ suite('ScrollbarState', () => {
});
test('inflates slider size with arrows', () => {
let actual = new ScrollbarState(12, 14, 0);
actual.setVisibleSize(339);
actual.setScrollSize(42423);
actual.setScrollPosition(32787);
let actual = new ScrollbarState(12, 14, 0, 339, 42423, 32787);
assert.equal(actual.getArrowSize(), 12);
assert.equal(actual.getScrollPosition(), 32787);

View File

@@ -237,6 +237,20 @@ suite('Event', function () {
assert.equal(calls, 2);
});
test('Debounce Event - leading reset', async function () {
const emitter = new Emitter<number>();
let debounced = Event.debounce(emitter.event, (l, e) => l ? l + 1 : 1, 0, /*leading=*/true);
let calls: number[] = [];
debounced((e) => calls.push(e));
emitter.fire(1);
emitter.fire(1);
await timeout(1);
assert.deepEqual(calls, [1, 1]);
});
test('Emitter - In Order Delivery', function () {
const a = new Emitter<string>();
const listener2Events: string[] = [];

View File

@@ -12,8 +12,8 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementChannel, GlobalExtensionEnablementServiceClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -113,6 +113,9 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
disposables.add(logService);
logService.info('main', JSON.stringify(configuration));
const mainProcessService = new MainProcessService(server, mainRouter);
services.set(IMainProcessService, mainProcessService);
const configurationService = new ConfigurationService(environmentService.settingsResource);
disposables.add(configurationService);
await configurationService.initialize();
@@ -124,8 +127,6 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IRequestService, new SyncDescriptor(RequestService));
services.set(ILoggerService, new SyncDescriptor(LoggerService));
const mainProcessService = new MainProcessService(server, mainRouter);
services.set(IMainProcessService, mainProcessService);
const electronService = createChannelSender<IElectronService>(mainProcessService.getChannel('electron'), { context: configuration.windowId });
services.set(IElectronService, electronService);
@@ -184,6 +185,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IUserDataAuthTokenService, new SyncDescriptor(UserDataAuthTokenService));
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', activeWindowRouter)));
services.set(IGlobalExtensionEnablementService, new GlobalExtensionEnablementServiceClient(server.getChannel('globalExtensionEnablement', activeWindowRouter)));
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));
services.set(ISettingsSyncService, new SyncDescriptor(SettingsSynchroniser));
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));

View File

@@ -171,7 +171,7 @@ export class CodeApplication extends Disposable {
app.on('web-contents-created', (_event: Event, contents) => {
contents.on('will-attach-webview', (event: Event, webPreferences, params) => {
const isValidWebviewSource = (source: string | undefined): boolean => {
const isValidWebviewSource = (source: string): boolean => {
if (!source) {
return false;
}
@@ -191,12 +191,11 @@ export class CodeApplication extends Disposable {
webPreferences.nodeIntegration = false;
// Verify URLs being loaded
// https://github.com/electron/electron/issues/21553
if (isValidWebviewSource(params.src) && isValidWebviewSource((webPreferences as { preloadURL: string }).preloadURL)) {
if (isValidWebviewSource(params.src) && isValidWebviewSource(webPreferences.preloadURL)) {
return;
}
delete (webPreferences as { preloadURL: string }).preloadURL; // https://github.com/electron/electron/issues/21553
delete webPreferences.preloadUrl;
// Otherwise prevent loading
this.logService.error('webContents#web-contents-created: Prevented webview attach');
@@ -498,27 +497,27 @@ export class CodeApplication extends Disposable {
this.logService.info(`Tracing: waiting for windows to get ready...`);
let recordingStopped = false;
const stopRecording = async (timeout: boolean) => {
const stopRecording = (timeout: boolean) => {
if (recordingStopped) {
return;
}
recordingStopped = true; // only once
const path = await contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`));
if (!timeout) {
if (this.dialogMainService) {
this.dialogMainService.showMessageBox({
type: 'info',
message: localize('trace.message', "Successfully created trace."),
detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
buttons: [localize('trace.ok', "Ok")]
}, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`), path => {
if (!timeout) {
if (this.dialogMainService) {
this.dialogMainService.showMessageBox({
type: 'info',
message: localize('trace.message', "Successfully created trace."),
detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
buttons: [localize('trace.ok', "Ok")]
}, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
}
} else {
this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
}
} else {
this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
}
});
};
// Wait up to 30s before creating the trace anyways

View File

@@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects';
import * as nls from 'vs/nls';
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme } from 'electron';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment } from 'electron';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -347,9 +347,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
});
this._win.webContents.session.webRequest.onHeadersReceived(null!, (details, callback) => {
const responseHeaders = details.responseHeaders as Record<string, (string) | (string[])>;
const responseHeaders = details.responseHeaders as { [key: string]: string[] };
const contentType = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
const contentType: string[] = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
if (contentType && Array.isArray(contentType) && contentType.some(x => x.toLowerCase().indexOf('image/svg') >= 0)) {
return callback({ cancel: true });
}
@@ -441,7 +441,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Inject headers when requests are incoming
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) =>
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) as Record<string, string> })));
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined } })));
}
private onWindowError(error: WindowError): void {
@@ -648,7 +648,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
if (windowConfig?.autoDetectHighContrast === false) {
autoDetectHighContrast = false;
}
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && nativeTheme.shouldUseInvertedColorScheme;
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme();
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;
// Title style related
@@ -1007,22 +1007,22 @@ export class CodeWindow extends Disposable implements ICodeWindow {
switch (visibility) {
case ('default'):
this._win.setMenuBarVisibility(!isFullscreen);
this._win.autoHideMenuBar = isFullscreen;
this._win.setAutoHideMenuBar(isFullscreen);
break;
case ('visible'):
this._win.setMenuBarVisibility(true);
this._win.autoHideMenuBar = false;
this._win.setAutoHideMenuBar(false);
break;
case ('toggle'):
this._win.setMenuBarVisibility(false);
this._win.autoHideMenuBar = true;
this._win.setAutoHideMenuBar(true);
break;
case ('hidden'):
this._win.setMenuBarVisibility(false);
this._win.autoHideMenuBar = false;
this._win.setAutoHideMenuBar(false);
break;
}
}

View File

@@ -14,7 +14,7 @@ import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/c
import { EditorOption, IEditorConstructionOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { IDimension } from 'vs/editor/common/editorCommon';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
class CSSBasedConfigurationCache {
@@ -87,6 +87,7 @@ export interface ISerializedFontInfo {
readonly typicalFullwidthCharacterWidth: number;
readonly canUseHalfwidthRightwardsArrow: boolean;
readonly spaceWidth: number;
middotWidth: number;
readonly maxDigitWidth: number;
}
@@ -159,6 +160,7 @@ class CSSBasedConfiguration extends Disposable {
const savedFontInfo = savedFontInfos[i];
// compatibility with older versions of VS Code which did not store this...
savedFontInfo.fontFeatureSettings = savedFontInfo.fontFeatureSettings || EditorFontLigatures.OFF;
savedFontInfo.middotWidth = savedFontInfo.middotWidth || savedFontInfo.spaceWidth;
const fontInfo = new FontInfo(savedFontInfo, false);
this._writeToCache(fontInfo, fontInfo);
}
@@ -183,6 +185,7 @@ class CSSBasedConfiguration extends Disposable {
typicalFullwidthCharacterWidth: Math.max(readConfig.typicalFullwidthCharacterWidth, 5),
canUseHalfwidthRightwardsArrow: readConfig.canUseHalfwidthRightwardsArrow,
spaceWidth: Math.max(readConfig.spaceWidth, 5),
middotWidth: Math.max(readConfig.middotWidth, 5),
maxDigitWidth: Math.max(readConfig.maxDigitWidth, 5),
}, false);
}
@@ -223,7 +226,8 @@ class CSSBasedConfiguration extends Disposable {
const rightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, monospace);
const halfwidthRightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, null);
this.createRequest('·', CharWidthRequestType.Regular, all, monospace);
// middle dot character
const middot = this.createRequest('·', CharWidthRequestType.Regular, all, monospace);
// monospace test: some characters
this.createRequest('|', CharWidthRequestType.Regular, all, monospace);
@@ -289,6 +293,7 @@ class CSSBasedConfiguration extends Disposable {
typicalFullwidthCharacterWidth: typicalFullwidthCharacter.width,
canUseHalfwidthRightwardsArrow: canUseHalfwidthRightwardsArrow,
spaceWidth: space.width,
middotWidth: middot.width,
maxDigitWidth: maxDigitWidth
}, canTrustBrowserZoomLevel);
}
@@ -333,7 +338,7 @@ export class Configuration extends CommonEditorConfiguration {
}
this._register(browser.onDidChangeZoomLevel(_ => this._recomputeOptions()));
this._register(this.accessibilityService.onDidChangeAccessibilitySupport(() => this._recomputeOptions()));
this._register(this.accessibilityService.onDidChangeScreenReaderOptimized(() => this._recomputeOptions()));
this._recomputeOptions();
}
@@ -374,7 +379,7 @@ export class Configuration extends CommonEditorConfiguration {
emptySelectionClipboard: browser.isWebKit || browser.isFirefox,
pixelRatio: browser.getPixelRatio(),
zoomLevel: browser.getZoomLevel(),
accessibilitySupport: this.accessibilityService.getAccessibilitySupport()
accessibilitySupport: this.accessibilityService.isScreenReaderOptimized() ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled
};
}

View File

@@ -363,6 +363,7 @@ class MouseDownOperation extends Disposable {
this._isActive = true;
this._mouseMoveMonitor.startMonitoring(
e.target,
e.buttons,
createMouseMoveEventMerger(null),
(e) => this._onMouseDownThenMove(e),
@@ -387,6 +388,7 @@ class MouseDownOperation extends Disposable {
if (!this._isActive) {
this._isActive = true;
this._mouseMoveMonitor.startMonitoring(
e.target,
e.buttons,
createMouseMoveEventMerger(null),
(e) => this._onMouseDownThenMove(e),

View File

@@ -17,6 +17,7 @@ import { HorizontalPosition } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
import * as dom from 'vs/base/browser/dom';
export interface IViewZoneData {
viewZoneId: string;
@@ -835,8 +836,17 @@ export class MouseTargetFactory {
}
private static _actualDoHitTestWithCaretRangeFromPoint(ctx: HitTestContext, coords: ClientCoordinates): IHitTestResult {
const range: Range = document.caretRangeFromPoint(coords.clientX, coords.clientY);
const shadowRoot = dom.getShadowRoot(ctx.viewDomNode);
let range: Range;
if (shadowRoot) {
if (typeof shadowRoot.caretRangeFromPoint === 'undefined') {
range = shadowCaretRangeFromPoint(shadowRoot, coords.clientX, coords.clientY);
} else {
range = shadowRoot.caretRangeFromPoint(coords.clientX, coords.clientY);
}
} else {
range = document.caretRangeFromPoint(coords.clientX, coords.clientY);
}
if (!range || !range.startContainer) {
return {
@@ -1009,3 +1019,94 @@ export class MouseTargetFactory {
};
}
}
export function shadowCaretRangeFromPoint(shadowRoot: ShadowRoot, x: number, y: number): Range {
const range = document.createRange();
// Get the element under the point
let el: Element | null = shadowRoot.elementFromPoint(x, y);
if (el !== null) {
// Get the last child of the element until its firstChild is a text node
// This assumes that the pointer is on the right of the line, out of the tokens
// and that we want to get the offset of the last token of the line
while (el && el.firstChild && el.firstChild.nodeType !== el.firstChild.TEXT_NODE) {
el = <Element>el.lastChild;
}
// Grab its rect
const rect = el.getBoundingClientRect();
// And its font
const font = window.getComputedStyle(el, null).getPropertyValue('font');
// And also its txt content
const text = (el as any).innerText;
// Position the pixel cursor at the left of the element
let pixelCursor = rect.left;
let offset = 0;
let step: number;
// If the point is on the right of the box put the cursor after the last character
if (x > rect.left + rect.width) {
offset = text.length;
} else {
const charWidthReader = CharWidthReader.getInstance();
// Goes through all the characters of the innerText, and checks if the x of the point
// belongs to the character.
for (let i = 0; i < text.length + 1; i++) {
// The step is half the width of the character
step = charWidthReader.getCharWidth(text.charAt(i), font) / 2;
// Move to the center of the character
pixelCursor += step;
// If the x of the point is smaller that the position of the cursor, the point is over that character
if (x < pixelCursor) {
offset = i;
break;
}
// Move between the current character and the next
pixelCursor += step;
}
}
// Creates a range with the text node of the element and set the offset found
range.setStart(el.firstChild!, offset);
range.setEnd(el.firstChild!, offset);
}
return range;
}
class CharWidthReader {
private static _INSTANCE: CharWidthReader | null = null;
public static getInstance(): CharWidthReader {
if (!CharWidthReader._INSTANCE) {
CharWidthReader._INSTANCE = new CharWidthReader();
}
return CharWidthReader._INSTANCE;
}
private readonly _cache: { [cacheKey: string]: number; };
private readonly _canvas: HTMLCanvasElement;
private constructor() {
this._cache = {};
this._canvas = document.createElement('canvas');
}
public getCharWidth(char: string, font: string): number {
const cacheKey = char + font;
if (this._cache[cacheKey]) {
return this._cache[cacheKey];
}
const context = this._canvas.getContext('2d')!;
context.font = font;
const metrics = context.measureText(char);
const width = metrics.width;
this._cache[cacheKey] = width;
return width;
}
}

View File

@@ -17,7 +17,7 @@ import { ViewController } from 'vs/editor/browser/view/viewController';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { RenderLineNumbersType, EditorOption, IComputedEditorOptions } from 'vs/editor/common/config/editorOptions';
import { RenderLineNumbersType, EditorOption, IComputedEditorOptions, EditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { WordCharacterClass, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
import { Position } from 'vs/editor/common/core/position';
@@ -62,8 +62,8 @@ export class TextAreaHandler extends ViewPart {
private _scrollLeft: number;
private _scrollTop: number;
private _accessibilitySupport: AccessibilitySupport;
private _accessibilityPageSize: number;
private _accessibilitySupport!: AccessibilitySupport;
private _accessibilityPageSize!: number;
private _contentLeft: number;
private _contentWidth: number;
private _contentHeight: number;
@@ -77,6 +77,7 @@ export class TextAreaHandler extends ViewPart {
*/
private _visibleTextArea: VisibleTextAreaData | null;
private _selections: Selection[];
private _modelSelections: Selection[];
/**
* The position at which the textarea was rendered.
@@ -99,8 +100,7 @@ export class TextAreaHandler extends ViewPart {
const options = this._context.configuration.options;
const layoutInfo = options.get(EditorOption.layoutInfo);
this._accessibilitySupport = options.get(EditorOption.accessibilitySupport);
this._accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
this._setAccessibilityOptions(options);
this._contentLeft = layoutInfo.contentLeft;
this._contentWidth = layoutInfo.contentWidth;
this._contentHeight = layoutInfo.height;
@@ -111,6 +111,7 @@ export class TextAreaHandler extends ViewPart {
this._visibleTextArea = null;
this._selections = [new Selection(1, 1, 1, 1)];
this._modelSelections = [new Selection(1, 1, 1, 1)];
this._lastRenderPosition = null;
// Text Area (The focus will always be in the textarea when the cursor is blinking)
@@ -149,24 +150,30 @@ export class TextAreaHandler extends ViewPart {
const textAreaInputHost: ITextAreaInputHost = {
getDataToCopy: (generateHTML: boolean): ClipboardDataToCopy => {
const rawTextToCopy = this._context.model.getPlainTextToCopy(this._selections, this._emptySelectionClipboard, platform.isWindows);
const rawTextToCopy = this._context.model.getPlainTextToCopy(this._modelSelections, this._emptySelectionClipboard, platform.isWindows);
const newLineCharacter = this._context.model.getEOL();
const isFromEmptySelection = (this._emptySelectionClipboard && this._selections.length === 1 && this._selections[0].isEmpty());
const isFromEmptySelection = (this._emptySelectionClipboard && this._modelSelections.length === 1 && this._modelSelections[0].isEmpty());
const multicursorText = (Array.isArray(rawTextToCopy) ? rawTextToCopy : null);
const text = (Array.isArray(rawTextToCopy) ? rawTextToCopy.join(newLineCharacter) : rawTextToCopy);
let html: string | null | undefined = undefined;
let mode: string | null = null;
if (generateHTML) {
if (CopyOptions.forceCopyWithSyntaxHighlighting || (this._copyWithSyntaxHighlighting && text.length < 65536)) {
html = this._context.model.getHTMLToCopy(this._selections, this._emptySelectionClipboard);
const richText = this._context.model.getRichTextToCopy(this._modelSelections, this._emptySelectionClipboard);
if (richText) {
html = richText.html;
mode = richText.mode;
}
}
}
return {
isFromEmptySelection,
multicursorText,
text,
html
html,
mode
};
},
@@ -220,11 +227,13 @@ export class TextAreaHandler extends ViewPart {
this._register(this._textAreaInput.onPaste((e: IPasteData) => {
let pasteOnNewLine = false;
let multicursorText: string[] | null = null;
let mode: string | null = null;
if (e.metadata) {
pasteOnNewLine = (this._emptySelectionClipboard && !!e.metadata.isFromEmptySelection);
multicursorText = (typeof e.metadata.multicursorText !== 'undefined' ? e.metadata.multicursorText : null);
mode = e.metadata.mode;
}
this._viewController.paste('keyboard', e.text, pasteOnNewLine, multicursorText);
this._viewController.paste('keyboard', e.text, pasteOnNewLine, multicursorText, mode);
}));
this._register(this._textAreaInput.onCut(() => {
@@ -344,14 +353,24 @@ export class TextAreaHandler extends ViewPart {
return options.get(EditorOption.ariaLabel);
}
private _setAccessibilityOptions(options: IComputedEditorOptions): void {
this._accessibilitySupport = options.get(EditorOption.accessibilitySupport);
const accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
if (this._accessibilitySupport === AccessibilitySupport.Enabled && accessibilityPageSize === EditorOptions.accessibilityPageSize.defaultValue) {
// If a screen reader is attached and the default value is not set we shuold automatically increase the page size to 1000 for a better experience
this._accessibilityPageSize = 1000;
} else {
this._accessibilityPageSize = accessibilityPageSize;
}
}
// --- begin event handlers
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
const options = this._context.configuration.options;
const layoutInfo = options.get(EditorOption.layoutInfo);
this._accessibilitySupport = options.get(EditorOption.accessibilitySupport);
this._accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
this._setAccessibilityOptions(options);
this._contentLeft = layoutInfo.contentLeft;
this._contentWidth = layoutInfo.contentWidth;
this._contentHeight = layoutInfo.height;
@@ -377,6 +396,7 @@ export class TextAreaHandler extends ViewPart {
}
public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean {
this._selections = e.selections.slice(0);
this._modelSelections = e.modelSelections.slice(0);
this._textAreaInput.writeScreenReaderContent('selection changed');
return true;
}

View File

@@ -41,12 +41,14 @@ export interface ClipboardDataToCopy {
multicursorText: string[] | null | undefined;
text: string;
html: string | null | undefined;
mode: string | null;
}
export interface ClipboardStoredMetadata {
version: 1;
isFromEmptySelection: boolean | undefined;
multicursorText: string[] | null | undefined;
mode: string | null;
}
export interface ITextAreaInputHost {
@@ -550,7 +552,8 @@ export class TextAreaInput extends Disposable {
const storedMetadata: ClipboardStoredMetadata = {
version: 1,
isFromEmptySelection: dataToCopy.isFromEmptySelection,
multicursorText: dataToCopy.multicursorText
multicursorText: dataToCopy.multicursorText,
mode: dataToCopy.mode
};
InMemoryClipboardMetadataManager.INSTANCE.set(
// When writing "LINE\r\n" to the clipboard and then pasting,

View File

@@ -308,6 +308,14 @@ export interface IPartialEditorMouseEvent {
readonly target: IMouseTarget | null;
}
/**
* A paste event originating from the editor.
*/
export interface IPasteEvent {
readonly range: Range;
readonly mode: string | null;
}
/**
* An overview ruler
* @internal
@@ -416,11 +424,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
/**
* An event emitted after composition has started.
*/
onCompositionStart(listener: () => void): IDisposable;
onDidCompositionStart(listener: () => void): IDisposable;
/**
* An event emitted after composition has ended.
*/
onCompositionEnd(listener: () => void): IDisposable;
onDidCompositionEnd(listener: () => void): IDisposable;
/**
* An event emitted when editing failed because the editor is read-only.
* @event
@@ -431,7 +439,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
* An event emitted when users paste text in the editor.
* @event
*/
onDidPaste(listener: (range: Range) => void): IDisposable;
onDidPaste(listener: (e: IPasteEvent) => void): IDisposable;
/**
* An event emitted on a "mouseup".
* @event
@@ -723,6 +731,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
getTelemetryData(): { [key: string]: any } | undefined;
/**
* Returns the editor's container dom node
*/
getContainerDomNode(): HTMLElement;
/**
* Returns the editor's dom node
*/

View File

@@ -182,7 +182,13 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
this._keydownListener = null;
}
public startMonitoring(initialButtons: number, merger: EditorMouseEventMerger, mouseMoveCallback: (e: EditorMouseEvent) => void, onStopCallback: () => void): void {
public startMonitoring(
initialElement: HTMLElement,
initialButtons: number,
merger: EditorMouseEventMerger,
mouseMoveCallback: (e: EditorMouseEvent) => void,
onStopCallback: () => void
): void {
// Add a <<capture>> keydown event listener that will cancel the monitoring
// if something other than a modifier key is pressed
@@ -199,7 +205,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));
};
this._globalMouseMoveMonitor.startMonitoring(initialButtons, myMerger, mouseMoveCallback, () => {
this._globalMouseMoveMonitor.startMonitoring(initialElement, initialButtons, myMerger, mouseMoveCallback, () => {
this._keydownListener!.dispose();
onStopCallback();
});

View File

@@ -89,7 +89,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC
return editorWithWidgetFocus;
}
abstract registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
abstract registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string, editor?: ICodeEditor): void;
abstract removeDecorationType(key: string): void;
abstract resolveDecorationOptions(decorationTypeKey: string | undefined, writable: boolean): IModelDecorationOptions;
@@ -120,6 +120,16 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC
return this._transientWatchers[uri].get(key);
}
public getTransientModelProperties(model: ITextModel): [string, any][] | undefined {
const uri = model.uri.toString();
if (!this._transientWatchers.hasOwnProperty(uri)) {
return undefined;
}
return this._transientWatchers[uri].keys().map(key => [key, this._transientWatchers[uri].get(key)]);
}
_removeWatcher(w: ModelTransientSettingWatcher): void {
delete this._transientWatchers[w.uri];
}
@@ -145,4 +155,8 @@ export class ModelTransientSettingWatcher {
public get(key: string): any {
return this._values[key];
}
public keys(): string[] {
return Object.keys(this._values);
}
}

View File

@@ -37,12 +37,13 @@ export interface ICodeEditorService {
*/
getFocusedCodeEditor(): ICodeEditor | null;
registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string, editor?: ICodeEditor): void;
removeDecorationType(key: string): void;
resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions;
setTransientModelProperty(model: ITextModel, key: string, value: any): void;
getTransientModelProperty(model: ITextModel, key: string): any;
getTransientModelProperties(model: ITextModel): [string, any][] | undefined;
getActiveCodeEditor(): ICodeEditor | null;
openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null>;

View File

@@ -14,31 +14,101 @@ import { IModelDecorationOptions, IModelDecorationOverviewRulerOptions, Overview
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { ITheme, IThemeService, ThemeColor } from 'vs/platform/theme/common/themeService';
class RefCountedStyleSheet {
private readonly _parent: CodeEditorServiceImpl;
private readonly _editorId: string;
public readonly styleSheet: HTMLStyleElement;
private _refCount: number;
constructor(parent: CodeEditorServiceImpl, editorId: string, styleSheet: HTMLStyleElement) {
this._parent = parent;
this._editorId = editorId;
this.styleSheet = styleSheet;
this._refCount = 0;
}
public ref(): void {
this._refCount++;
}
public unref(): void {
this._refCount--;
if (this._refCount === 0) {
this.styleSheet.parentNode?.removeChild(this.styleSheet);
this._parent._removeEditorStyleSheets(this._editorId);
}
}
}
class GlobalStyleSheet {
public readonly styleSheet: HTMLStyleElement;
constructor(styleSheet: HTMLStyleElement) {
this.styleSheet = styleSheet;
}
public ref(): void {
}
public unref(): void {
}
}
export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
private readonly _styleSheet: HTMLStyleElement;
private _globalStyleSheet: GlobalStyleSheet | null;
private readonly _decorationOptionProviders = new Map<string, IModelDecorationOptionsProvider>();
private readonly _editorStyleSheets = new Map<string, RefCountedStyleSheet>();
private readonly _themeService: IThemeService;
constructor(@IThemeService themeService: IThemeService, styleSheet = dom.createStyleSheet()) {
constructor(@IThemeService themeService: IThemeService, styleSheet: HTMLStyleElement | null = null) {
super();
this._styleSheet = styleSheet;
this._globalStyleSheet = styleSheet ? new GlobalStyleSheet(styleSheet) : null;
this._themeService = themeService;
}
public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void {
private _getOrCreateGlobalStyleSheet(): GlobalStyleSheet {
if (!this._globalStyleSheet) {
this._globalStyleSheet = new GlobalStyleSheet(dom.createStyleSheet());
}
return this._globalStyleSheet;
}
private _getOrCreateStyleSheet(editor: ICodeEditor | undefined): GlobalStyleSheet | RefCountedStyleSheet {
if (!editor) {
return this._getOrCreateGlobalStyleSheet();
}
const domNode = editor.getContainerDomNode();
if (!dom.isInShadowDOM(domNode)) {
return this._getOrCreateGlobalStyleSheet();
}
const editorId = editor.getId();
if (!this._editorStyleSheets.has(editorId)) {
const refCountedStyleSheet = new RefCountedStyleSheet(this, editorId, dom.createStyleSheet(domNode));
this._editorStyleSheets.set(editorId, refCountedStyleSheet);
}
return this._editorStyleSheets.get(editorId)!;
}
_removeEditorStyleSheets(editorId: string): void {
this._editorStyleSheets.delete(editorId);
}
public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string, editor?: ICodeEditor): void {
let provider = this._decorationOptionProviders.get(key);
if (!provider) {
const styleSheet = this._getOrCreateStyleSheet(editor);
const providerArgs: ProviderArguments = {
styleSheet: this._styleSheet,
styleSheet: styleSheet.styleSheet,
key: key,
parentTypeKey: parentTypeKey,
options: options || Object.create(null)
};
if (!parentTypeKey) {
provider = new DecorationTypeOptionsProvider(this._themeService, providerArgs);
provider = new DecorationTypeOptionsProvider(this._themeService, styleSheet, providerArgs);
} else {
provider = new DecorationSubTypeOptionsProvider(this._themeService, providerArgs);
provider = new DecorationSubTypeOptionsProvider(this._themeService, styleSheet, providerArgs);
}
this._decorationOptionProviders.set(key, provider);
}
@@ -76,13 +146,16 @@ interface IModelDecorationOptionsProvider extends IDisposable {
class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvider {
private readonly _styleSheet: GlobalStyleSheet | RefCountedStyleSheet;
public refCount: number;
private readonly _parentTypeKey: string | undefined;
private _beforeContentRules: DecorationCSSRules | null;
private _afterContentRules: DecorationCSSRules | null;
constructor(themeService: IThemeService, providerArgs: ProviderArguments) {
constructor(themeService: IThemeService, styleSheet: GlobalStyleSheet | RefCountedStyleSheet, providerArgs: ProviderArguments) {
this._styleSheet = styleSheet;
this._styleSheet.ref();
this._parentTypeKey = providerArgs.parentTypeKey;
this.refCount = 0;
@@ -110,6 +183,7 @@ class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvide
this._afterContentRules.dispose();
this._afterContentRules = null;
}
this._styleSheet.unref();
}
}
@@ -124,6 +198,7 @@ interface ProviderArguments {
class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
private readonly _disposables = new DisposableStore();
private readonly _styleSheet: GlobalStyleSheet | RefCountedStyleSheet;
public refCount: number;
public className: string | undefined;
@@ -136,7 +211,9 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
public overviewRuler: IModelDecorationOverviewRulerOptions | undefined;
public stickiness: TrackedRangeStickiness | undefined;
constructor(themeService: IThemeService, providerArgs: ProviderArguments) {
constructor(themeService: IThemeService, styleSheet: GlobalStyleSheet | RefCountedStyleSheet, providerArgs: ProviderArguments) {
this._styleSheet = styleSheet;
this._styleSheet.ref();
this.refCount = 0;
const createCSSRules = (type: ModelDecorationCSSRuleType) => {
@@ -202,6 +279,7 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
public dispose(): void {
this._disposables.dispose();
this._styleSheet.unref();
}
}

View File

@@ -37,7 +37,7 @@ export interface IMouseDispatchData {
export interface ICommandDelegate {
executeEditorCommand(editorCommand: CoreEditorCommand, args: any): void;
paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null): void;
paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null): void;
type(source: string, text: string): void;
replacePreviousChar(source: string, text: string, replaceCharCnt: number): void;
compositionStart(source: string): void;
@@ -69,8 +69,8 @@ export class ViewController {
this.commandDelegate.executeEditorCommand(editorCommand, args);
}
public paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null): void {
this.commandDelegate.paste(source, text, pasteOnNewLine, multicursorText);
public paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null): void {
this.commandDelegate.paste(source, text, pasteOnNewLine, multicursorText, mode);
}
public type(source: string, text: string): void {

View File

@@ -38,6 +38,7 @@ import { ViewCursors } from 'vs/editor/browser/viewParts/viewCursors/viewCursors
import { ViewZones } from 'vs/editor/browser/viewParts/viewZones/viewZones';
import { Cursor } from 'vs/editor/common/controller/cursor';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
@@ -525,10 +526,15 @@ export class View extends ViewEventHandler {
}
public layoutContentWidget(widgetData: IContentWidgetData): void {
const newPosition = widgetData.position ? widgetData.position.position : null;
const newRange = widgetData.position ? widgetData.position.range || null : null;
let newRange = widgetData.position ? widgetData.position.range || null : null;
if (newRange === null) {
const newPosition = widgetData.position ? widgetData.position.position : null;
if (newPosition !== null) {
newRange = new Range(newPosition.lineNumber, newPosition.column, newPosition.lineNumber, newPosition.column);
}
}
const newPreference = widgetData.position ? widgetData.position.preference : null;
this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newRange, newPreference);
this.contentWidgets.setWidgetPosition(widgetData.widget, newRange, newPreference);
this._scheduleRender();
}

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