Merge branch 'ads-master-vscode-2020-04-30T00-53-40'

This commit is contained in:
AzureDataStudio
2020-04-30 01:33:00 -07:00
413 changed files with 7192 additions and 8756 deletions

View File

@@ -485,7 +485,8 @@
"**/{vs,sql}/workbench/services/**/common/**",
"**/{vs,sql}/workbench/api/**/common/**",
"vs/workbench/contrib/files/common/editors/fileEditorInput", // this should be fine, it only accesses constants from contrib
"vscode-textmate"
"vscode-textmate",
"vscode-oniguruma"
]
},
{
@@ -519,7 +520,8 @@
"onigasm-umd",
"sanitize-html",
"@angular/*",
"rxjs/**"
"rxjs/**",
"vscode-oniguruma"
]
},
{

1
.vscode/launch.json vendored
View File

@@ -79,7 +79,6 @@
"type": "pwa-chrome",
"request": "launch",
"name": "Launch azuredatastudio",
"browserLaunchLocation": "workspace",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat"
},

View File

@@ -1,9 +1,19 @@
# Query: \\w+\\?\\..+![(.[]
# Query: \\w+\\?\\.\\w+![(.[]
# Flags: RegExp
# ContextLines: 2
2 results - 2 files
src/vs/base/browser/ui/tree/asyncDataTree.ts:
270 } : undefined,
271 isChecked: options.ariaProvider!.isChecked ? (e) => {
272: return options.ariaProvider?.isChecked!(e.element as T);
273 } : undefined
274 },
243 } : () => 'treeitem',
244 isChecked: options.accessibilityProvider!.isChecked ? (e) => {
245: return !!(options.accessibilityProvider?.isChecked!(e.element as T));
246 } : undefined,
247 getAriaLabel(e) {
src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts:
254
255 return debugDynamicExtensions.map(e => {
256: const type = e.contributes?.debuggers![0].type!;
257 return {
258 label: this.getDebuggerLabel(type)!,

View File

@@ -7,7 +7,8 @@
"**/.DS_Store": true,
"build/**/*.js": {
"when": "$(basename).ts"
}
},
"src/vs/server": false
},
"files.associations": {
"cglicenses.json": "jsonc"
@@ -24,7 +25,8 @@
"test/smoke/out/**": true,
"test/automation/out/**": true,
"test/integration/browser/out/**": true,
"src/vs/base/test/node/uri.test.data.txt": true
"src/vs/base/test/node/uri.test.data.txt": true,
"src/vs/server": false
},
"lcov.path": [
"./.build/coverage/lcov.info",

View File

@@ -19,13 +19,6 @@ vscode-sqlite3/build/**
vscode-sqlite3/src/**
!vscode-sqlite3/build/Release/*.node
oniguruma/binding.gyp
oniguruma/build/**
oniguruma/src/**
oniguruma/deps/**
!oniguruma/build/Release/*.node
!oniguruma/src/*.js
windows-mutex/binding.gyp
windows-mutex/build/**
windows-mutex/src/**

View File

@@ -244,7 +244,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const deps = gulp.src(dependenciesSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore')))
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*', '**/*.wasm'], 'app/node_modules.asar'));
let all = es.merge(
packageJsonStream,

View File

@@ -187,6 +187,7 @@ const excludedExtensions = [
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'vscode-notebook-tests',
'integration-tests',
];
// {{SQL CARBON EDIT}}

View File

@@ -221,6 +221,7 @@ const excludedExtensions = [
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'vscode-notebook-tests',
'integration-tests', // {{SQL CARBON EDIT}}
];

View File

@@ -69,12 +69,7 @@ function loader(src, bundledFileHeader, bundleLoader) {
this.emit('data', data);
}
}))
.pipe(util.loadSourcemaps())
.pipe(concat('vs/loader.js'))
.pipe(es.mapSync(function (f) {
f.sourceMap.sourceRoot = util.toFileUri(path.join(REPO_ROOT_PATH, 'src'));
return f;
})));
.pipe(concat('vs/loader.js')));
}
function toConcatStream(src, bundledFileHeader, sources, dest) {
const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);

View File

@@ -81,12 +81,7 @@ function loader(src: string, bundledFileHeader: string, bundleLoader: boolean):
this.emit('data', data);
}
}))
.pipe(util.loadSourcemaps())
.pipe(concat('vs/loader.js'))
.pipe(es.mapSync<FileSourceMap, FileSourceMap>(function (f) {
f.sourceMap.sourceRoot = util.toFileUri(path.join(REPO_ROOT_PATH, 'src'));
return f;
}))
);
}

View File

@@ -48,7 +48,7 @@
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"terser": "4.3.8",
"typescript": "^3.9.0-dev.20200420",
"typescript": "^3.9.0-dev.20200427",
"vsce": "1.48.0",
"vscode-telemetry-extractor": "^1.5.4",
"xml2js": "^0.4.17"

View File

@@ -3462,10 +3462,10 @@ typescript@^3.0.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
typescript@^3.9.0-dev.20200420:
version "3.9.0-dev.20200420"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.0-dev.20200420.tgz#99c2bc0936dbf4479b0b5260d80475ed494b1532"
integrity sha512-36MW6V+oXNnsSgliSjUWvtOkO21g9+iFGHPFv+O06HsCl3dcuqzBac17m8xuOuWo1LUlEgS6yAnD9fiVgvmCfg==
typescript@^3.9.0-dev.20200427:
version "3.9.0-dev.20200427"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.0-dev.20200427.tgz#e42d606d938575dfb7b0b66f04a31b5f0eb0be57"
integrity sha512-ja/GhL7BHT+VQZiLoYMGJt2CP1Pdr0EhYefv4LLw4tVooSuCDB8SDKT/i/HwsoPgQ4ZaYfg1vPl+1RhiO3bwJg==
typical@^4.0.0:
version "4.0.0"

View File

@@ -169,5 +169,37 @@
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
]
},
{
// Reason: The license at https://github.com/floatdrop/pinkie/blob/master/license
// cannot be found by the OSS tool automatically.
"name": "pinkie",
"fullLicenseText": [
"The MIT License (MIT)",
"",
"Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in",
"all copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN",
"THE SOFTWARE."
]
},
{
"name": "big-integer",
"prependLicenseText": ["Copyright released to public domain"]
}
]

View File

@@ -21,6 +21,13 @@
"language": "dockerfile",
"scopeName": "source.dockerfile",
"path": "./syntaxes/docker.tmLanguage.json"
}]
}],
"configurationDefaults": {
"[dockerfile]": {
"editor.quickSuggestions": {
"strings": true
}
}
}
}
}
}

View File

@@ -609,10 +609,6 @@
"command": "git.pullRebase",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
},
{
"command": "git.pullFrom",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
},
{
"command": "git.merge",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
@@ -1669,6 +1665,18 @@
"scope": "resource",
"default": true,
"description": "%config.showCommitInput%"
},
"git.terminalAuthentication": {
"type": "boolean",
"scope": "resource",
"default": true,
"description": "%config.terminalAuthentication%"
},
"git.githubAuthentication": {
"type": "boolean",
"scope": "resource",
"default": true,
"description": "%config.githubAuthentication%"
}
}
},
@@ -1781,6 +1789,7 @@
"ignore"
],
"filenames": [
".gitignore_global",
".gitignore"
],
"configuration": "./languages/ignore.language-configuration.json"

View File

@@ -144,6 +144,8 @@
"config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.",
"config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.",
"config.showCommitInput": "Controls whether to show the commit input in the Git source control panel.",
"config.terminalAuthentication": "Controls whether to enable VS Code to be the authentication handler for git processes spawned in the integrated terminal. Note: terminals need to be restarted to pick up a change in this setting.",
"config.githubAuthentication": "Controls whether to enable automatic GitHub authentication for git commands within VS Code.",
"colors.added": "Color for added resources.",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",

View File

@@ -5,7 +5,7 @@
import { Model } from '../model';
import { Repository as BaseRepository, Resource } from '../repository';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider } from './git';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider, CredentialsProvider } from './git';
import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands } from 'vscode';
import { mapEvent } from '../util';
import { toGitUri } from '../uri';
@@ -183,6 +183,10 @@ export class ApiRepository implements Repository {
return this._repository.removeRemote(name);
}
renameRemote(name: string, newName: string): Promise<void> {
return this._repository.renameRemote(name, newName);
}
fetch(remote?: string | undefined, ref?: string | undefined, depth?: number | undefined): Promise<void> {
return this._repository.fetch(remote, ref, depth);
}
@@ -248,10 +252,21 @@ export class ApiImpl implements API {
return result ? new ApiRepository(result) : null;
}
async init(root: Uri): Promise<Repository | null> {
const path = root.fsPath;
await this._model.git.init(path);
await this._model.openRepository(path);
return this.getRepository(root) || null;
}
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
return this._model.registerRemoteSourceProvider(provider);
}
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
return this._model.registerCredentialsProvider(provider);
}
constructor(private _model: Model) { }
}

View File

@@ -179,6 +179,7 @@ export interface Repository {
addRemote(name: string, url: string): Promise<void>;
removeRemote(name: string): Promise<void>;
renameRemote(name: string, newName: string): Promise<void>;
fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
pull(unshallow?: boolean): Promise<void>;
@@ -203,6 +204,15 @@ export interface RemoteSourceProvider {
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
}
export interface Credentials {
readonly username: string;
readonly password: string;
}
export interface CredentialsProvider {
getCredentials(host: Uri): ProviderResult<Credentials>;
}
export type APIState = 'uninitialized' | 'initialized';
export interface API {
@@ -215,7 +225,10 @@ export interface API {
toGitUri(uri: Uri, ref: string): Uri;
getRepository(uri: Uri): Repository | null;
init(root: Uri): Promise<Repository | null>;
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
registerCredentialsProvider(provider: CredentialsProvider): Disposable;
}
export interface GitExtension {

View File

@@ -1,5 +1,5 @@
#!/bin/sh
VSCODE_GIT_ASKPASS_PIPE=`mktemp`
VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
cat $VSCODE_GIT_ASKPASS_PIPE
rm $VSCODE_GIT_ASKPASS_PIPE
rm $VSCODE_GIT_ASKPASS_PIPE

View File

@@ -3,36 +3,60 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { window, InputBoxOptions } from 'vscode';
import { IDisposable } from './util';
import { window, InputBoxOptions, Uri, OutputChannel, Disposable } from 'vscode';
import { IDisposable, EmptyDisposable, toDisposable } from './util';
import * as path from 'path';
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
export interface AskpassEnvironment {
GIT_ASKPASS: string;
ELECTRON_RUN_AS_NODE?: string;
VSCODE_GIT_ASKPASS_NODE?: string;
VSCODE_GIT_ASKPASS_MAIN?: string;
VSCODE_GIT_ASKPASS_HANDLE?: string;
}
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
import { CredentialsProvider, Credentials } from './api/git';
export class Askpass implements IIPCHandler {
private disposable: IDisposable;
private disposable: IDisposable = EmptyDisposable;
private cache = new Map<string, Credentials>();
private credentialsProviders = new Set<CredentialsProvider>();
static getDisabledEnv(): AskpassEnvironment {
return {
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
};
static async create(outputChannel: OutputChannel, context?: string): Promise<Askpass> {
try {
return new Askpass(await createIPCServer(context));
} catch (err) {
outputChannel.appendLine(`[error] Failed to create git askpass IPC: ${err}`);
return new Askpass();
}
}
constructor(ipc: IIPCServer) {
this.disposable = ipc.registerHandler('askpass', this);
private constructor(private ipc?: IIPCServer) {
if (ipc) {
this.disposable = ipc.registerHandler('askpass', this);
}
}
async handle({ request, host }: { request: string, host: string }): Promise<string> {
const uri = Uri.parse(host);
const authority = uri.authority.replace(/^.*@/, '');
const password = /password/i.test(request);
const cached = this.cache.get(authority);
if (cached && password) {
this.cache.delete(authority);
return cached.password;
}
if (!password) {
for (const credentialsProvider of this.credentialsProviders) {
try {
const credentials = await credentialsProvider.getCredentials(uri);
if (credentials) {
this.cache.set(authority, credentials);
setTimeout(() => this.cache.delete(authority), 60_000);
return credentials.username;
}
} catch { }
}
}
const options: InputBoxOptions = {
password: /password/i.test(request),
password,
placeHolder: request,
prompt: `Git: ${host}`,
ignoreFocusOut: true
@@ -41,15 +65,26 @@ export class Askpass implements IIPCHandler {
return await window.showInputBox(options) || '';
}
getEnv(): AskpassEnvironment {
getEnv(): { [key: string]: string; } {
if (!this.ipc) {
return {
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
};
}
return {
ELECTRON_RUN_AS_NODE: '1',
...this.ipc.getEnv(),
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
VSCODE_GIT_ASKPASS_NODE: process.execPath,
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
};
}
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
this.credentialsProviders.add(provider);
return toDisposable(() => this.credentialsProviders.delete(provider));
}
dispose(): void {
this.disposable.dispose();
}

View File

@@ -524,7 +524,7 @@ export class CommandCenter {
quickpick.ignoreFocusOut = true;
const providers = this.model.getRemoteProviders()
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {1}", provider.name), alwaysShow: true, provider }));
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {0}", provider.name), alwaysShow: true, provider }));
quickpick.placeholder = providers.length === 0
? localize('provide url', "Provide repository URL.")
@@ -2560,6 +2560,14 @@ export class CommandCenter {
type = 'warning';
options.modal = false;
break;
case GitErrorCodes.AuthenticationFailed:
const regex = /Authentication failed for '(.*)'/i;
const match = regex.exec(err.stderr || String(err));
message = match
? localize('auth failed specific', "Failed to authenticate to git remote:\n\n{0}", match[1])
: localize('auth failed', "Failed to authenticate to git remote.");
break;
case GitErrorCodes.NoUserNameConfigured:
case GitErrorCodes.NoUserEmailConfigured:
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");

View File

@@ -306,7 +306,7 @@ export interface IGitOptions {
function getGitErrorCode(stderr: string): string | undefined {
if (/Another git process seems to be running in this repository|If no other git process is currently running/.test(stderr)) {
return GitErrorCodes.RepositoryIsLocked;
} else if (/Authentication failed/.test(stderr)) {
} else if (/Authentication failed/i.test(stderr)) {
return GitErrorCodes.AuthenticationFailed;
} else if (/Not a git repository/i.test(stderr)) {
return GitErrorCodes.NotAGitRepository;
@@ -1498,7 +1498,12 @@ export class Repository {
}
async removeRemote(name: string): Promise<void> {
const args = ['remote', 'rm', name];
const args = ['remote', 'remove', name];
await this.run(args);
}
async renameRemote(name: string, newName: string): Promise<void> {
const args = ['remote', 'rename', name, newName];
await this.run(args);
}

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CredentialsProvider, Credentials } from './api/git';
import { IDisposable, filterEvent, EmptyDisposable } from './util';
import { workspace, Uri, AuthenticationSession, authentication } from 'vscode';
import { Askpass } from './askpass';
export class GitHubCredentialProvider implements CredentialsProvider {
async getCredentials(host: Uri): Promise<Credentials | undefined> {
if (!/github\.com/i.test(host.authority)) {
return;
}
const session = await this.getSession();
return { username: session.account.id, password: await session.getAccessToken() };
}
private async getSession(): Promise<AuthenticationSession> {
const authenticationSessions = await authentication.getSessions('github', ['repo']);
if (authenticationSessions.length) {
return await authenticationSessions[0];
} else {
return await authentication.login('github', ['repo']);
}
}
}
export class GithubCredentialProviderManager {
private providerDisposable: IDisposable = EmptyDisposable;
private readonly disposable: IDisposable;
private _enabled = false;
private set enabled(enabled: boolean) {
if (this._enabled === enabled) {
return;
}
this._enabled = enabled;
if (enabled) {
this.providerDisposable = this.askpass.registerCredentialsProvider(new GitHubCredentialProvider());
} else {
this.providerDisposable.dispose();
}
}
constructor(private readonly askpass: Askpass) {
this.disposable = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'))(this.refresh, this);
this.refresh();
}
private refresh(): void {
this.enabled = workspace.getConfiguration('git', null).get('githubAuthentication', true);
}
dispose(): void {
this.enabled = false;
this.disposable.dispose();
}
}

View File

@@ -11,27 +11,42 @@ import * as os from 'os';
import * as fs from 'fs';
import * as crypto from 'crypto';
function getIPCHandlePath(nonce: string): string {
function getIPCHandlePath(id: string): string {
if (process.platform === 'win32') {
return `\\\\.\\pipe\\vscode-git-ipc-${nonce}-sock`;
return `\\\\.\\pipe\\vscode-git-${id}-sock`;
}
if (process.env['XDG_RUNTIME_DIR']) {
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-ipc-${nonce}.sock`);
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-${id}.sock`);
}
return path.join(os.tmpdir(), `vscode-git-ipc-${nonce}.sock`);
return path.join(os.tmpdir(), `vscode-git-${id}.sock`);
}
export interface IIPCHandler {
handle(request: any): Promise<any>;
}
export async function createIPCServer(): Promise<IIPCServer> {
export async function createIPCServer(context?: string): Promise<IIPCServer> {
const server = http.createServer();
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
const nonce = buffer.toString('hex');
const ipcHandlePath = getIPCHandlePath(nonce);
const hash = crypto.createHash('sha1');
if (!context) {
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
hash.update(buffer);
} else {
hash.update(context);
}
const ipcHandlePath = getIPCHandlePath(hash.digest('hex').substr(0, 10));
if (process.platform !== 'win32') {
try {
await fs.promises.unlink(ipcHandlePath);
} catch {
// noop
}
}
return new Promise((c, e) => {
try {
@@ -46,7 +61,7 @@ export async function createIPCServer(): Promise<IIPCServer> {
export interface IIPCServer extends Disposable {
readonly ipcHandlePath: string | undefined;
getEnv(): any;
getEnv(): { [key: string]: string; };
registerHandler(name: string, handler: IIPCHandler): Disposable;
}
@@ -91,7 +106,7 @@ class IPCServer implements IIPCServer, Disposable {
});
}
getEnv(): any {
getEnv(): { [key: string]: string; } {
return { VSCODE_GIT_IPC_HANDLE: this.ipcHandlePath };
}

View File

@@ -20,9 +20,10 @@ import { GitProtocolHandler } from './protocolHandler';
import { GitExtensionImpl } from './api/extension';
// import * as path from 'path';
// import * as fs from 'fs';
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
import { GitTimelineProvider } from './timelineProvider';
import { registerAPICommands } from './api/api1';
import { GithubCredentialProviderManager } from './github';
import { TerminalEnvironmentManager } from './terminal';
const deactivateTasks: { (): Promise<any>; }[] = [];
@@ -36,27 +37,18 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
const pathHint = workspace.getConfiguration('git').get<string>('path');
const info = await findGit(pathHint, path => outputChannel.appendLine(localize('looking', "Looking for git in: {0}", path)));
let env: any = {};
let ipc: IIPCServer | undefined;
const askpass = await Askpass.create(outputChannel, context.storagePath);
disposables.push(askpass);
try {
ipc = await createIPCServer();
disposables.push(ipc);
env = { ...env, ...ipc.getEnv() };
} catch {
// noop
}
const env = askpass.getEnv();
const terminalEnvironmentManager = new TerminalEnvironmentManager(context, env);
disposables.push(terminalEnvironmentManager);
if (ipc) {
const askpass = new Askpass(ipc);
disposables.push(askpass);
env = { ...env, ...askpass.getEnv() };
} else {
env = { ...env, ...Askpass.getDisabledEnv() };
}
const githubCredentialProviderManager = new GithubCredentialProviderManager(askpass);
context.subscriptions.push(githubCredentialProviderManager);
const git = new Git({ gitPath: info.path, version: info.version, env });
const model = new Model(git, context.globalState, outputChannel);
const model = new Model(git, askpass, context.globalState, outputChannel);
disposables.push(model);
const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`);

View File

@@ -12,7 +12,8 @@ import * as path from 'path';
import * as fs from 'fs';
import * as nls from 'vscode-nls';
import { fromGitUri } from './uri';
import { GitErrorCodes, APIState as State, RemoteSourceProvider } from './api/git';
import { GitErrorCodes, APIState as State, RemoteSourceProvider, CredentialsProvider } from './api/git';
import { Askpass } from './askpass';
const localize = nls.loadMessageBundle();
@@ -78,7 +79,7 @@ export class Model {
private disposables: Disposable[] = [];
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel) {
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
@@ -454,6 +455,10 @@ export class Model {
return toDisposable(() => this.remoteProviders.delete(provider));
}
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
return this.askpass.registerCredentialsProvider(provider);
}
getRemoteProviders(): RemoteSourceProvider[] {
return [...this.remoteProviders.values()];
}

View File

@@ -1096,6 +1096,10 @@ export class Repository implements Disposable {
await this.run(Operation.Remote, () => this.repository.removeRemote(name));
}
async renameRemote(name: string, newName: string): Promise<void> {
await this.run(Operation.Remote, () => this.repository.renameRemote(name, newName));
}
@throttle
async fetchDefault(options: { silent?: boolean } = {}): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch(options));

View File

@@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext, workspace } from 'vscode';
import { filterEvent, IDisposable } from './util';
export class TerminalEnvironmentManager {
private readonly disposable: IDisposable;
private _enabled = false;
private set enabled(enabled: boolean) {
if (this._enabled === enabled) {
return;
}
this._enabled = enabled;
this.context.environmentVariableCollection.clear();
if (enabled) {
for (const name of Object.keys(this.env)) {
this.context.environmentVariableCollection.replace(name, this.env[name]);
}
}
}
constructor(private readonly context: ExtensionContext, private readonly env: { [key: string]: string }) {
this.disposable = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'))
(this.refresh, this);
this.refresh();
}
private refresh(): void {
this.enabled = workspace.getConfiguration('git', null).get('terminalAuthentication', true);
}
dispose(): void {
this.disposable.dispose();
}
}

View File

@@ -14,6 +14,22 @@
"activationEvents": [
"*"
],
"contributes": {
"commands": [
{
"command": "github.provide-token",
"title": "Manually Provide Token"
}
],
"menus": {
"commandPalette": [
{
"command": "github.provide-token",
"when": "false"
}
]
}
},
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js",
"scripts": {

View File

@@ -18,6 +18,10 @@ export async function activate(context: vscode.ExtensionContext) {
await loginService.initialize();
context.subscriptions.push(vscode.commands.registerCommand('github.provide-token', () => {
return loginService.manuallyProvideToken();
}));
vscode.authentication.registerAuthenticationProvider({
id: 'github',
displayName: 'GitHub',

View File

@@ -6,7 +6,7 @@
import * as vscode from 'vscode';
import * as uuid from 'uuid';
import { keychain } from './common/keychain';
import { GitHubServer } from './githubServer';
import { GitHubServer, NETWORK_ERROR } from './githubServer';
import Logger from './common/logger';
export const onDidChangeSessions = new vscode.EventEmitter<vscode.AuthenticationSessionsChangeEvent>();
@@ -38,13 +38,26 @@ export class GitHubAuthenticationProvider {
private _githubServer = new GitHubServer();
public async initialize(): Promise<void> {
this._sessions = await this.readSessions();
try {
this._sessions = await this.readSessions();
} catch (e) {
// Ignore, network request failed
}
// TODO revert Cannot validate tokens from auth server, no available clientId
// await this.validateSessions();
this.pollForChange();
}
private pollForChange() {
setTimeout(async () => {
const storedSessions = await this.readSessions();
let storedSessions: vscode.AuthenticationSession[];
try {
storedSessions = await this.readSessions();
} catch (e) {
// Ignore, network request failed
return;
}
const added: string[] = [];
const removed: string[] = [];
@@ -53,6 +66,7 @@ export class GitHubAuthenticationProvider {
const matchesExisting = this._sessions.some(s => s.id === session.id);
// Another window added a session to the keychain, add it to our state as well
if (!matchesExisting) {
Logger.info('Adding session found in keychain');
this._sessions.push(session);
added.push(session.id);
}
@@ -62,6 +76,7 @@ export class GitHubAuthenticationProvider {
const matchesExisting = storedSessions.some(s => s.id === session.id);
// Another window has logged out, remove from our state
if (!matchesExisting) {
Logger.info('Removing session no longer found in keychain');
const sessionIndex = this._sessions.findIndex(s => s.id === session.id);
if (sessionIndex > -1) {
this._sessions.splice(sessionIndex, 1);
@@ -84,35 +99,36 @@ export class GitHubAuthenticationProvider {
if (storedSessions) {
try {
const sessionData: (SessionData | OldSessionData)[] = JSON.parse(storedSessions);
const sessionPromises = sessionData.map(async (session: SessionData | OldSessionData): Promise<vscode.AuthenticationSession | undefined> => {
try {
const needsUserInfo = isOldSessionData(session) || !session.account;
let userInfo: { id: string, accountName: string };
if (needsUserInfo) {
userInfo = await this._githubServer.getUserInfo(session.accessToken);
}
return {
id: session.id,
account: {
displayName: isOldSessionData(session)
? session.accountName
: session.account?.displayName ?? userInfo!.accountName,
id: isOldSessionData(session)
? userInfo!.id
: session.account?.id ?? userInfo!.id
},
scopes: session.scopes,
getAccessToken: () => Promise.resolve(session.accessToken)
};
} catch (e) {
return undefined;
const sessionPromises = sessionData.map(async (session: SessionData | OldSessionData): Promise<vscode.AuthenticationSession> => {
const needsUserInfo = isOldSessionData(session) || !session.account;
let userInfo: { id: string, accountName: string };
if (needsUserInfo) {
userInfo = await this._githubServer.getUserInfo(session.accessToken);
}
return {
id: session.id,
account: {
displayName: isOldSessionData(session)
? session.accountName
: session.account?.displayName ?? userInfo!.accountName,
id: isOldSessionData(session)
? userInfo!.id
: session.account?.id ?? userInfo!.id
},
scopes: session.scopes,
getAccessToken: () => Promise.resolve(session.accessToken)
};
});
return (await Promise.all(sessionPromises)).filter((x: vscode.AuthenticationSession | undefined): x is vscode.AuthenticationSession => !!x);
return Promise.all(sessionPromises);
} catch (e) {
if (e === NETWORK_ERROR) {
return [];
}
Logger.error(`Error reading sessions: ${e}`);
await keychain.deleteToken();
}
}
@@ -154,6 +170,10 @@ export class GitHubAuthenticationProvider {
}
}
public async manuallyProvideToken(): Promise<void> {
this._githubServer.manuallyProvideToken();
}
private async tokenToSession(token: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
const userInfo = await this._githubServer.getUserInfo(token);
return {
@@ -180,13 +200,15 @@ export class GitHubAuthenticationProvider {
public async logout(id: string) {
const sessionIndex = this._sessions.findIndex(session => session.id === id);
if (sessionIndex > -1) {
const session = this._sessions.splice(sessionIndex, 1)[0];
const token = await session.getAccessToken();
try {
await this._githubServer.revokeToken(token);
} catch (_) {
// ignore, should still remove from keychain
}
this._sessions.splice(sessionIndex, 1);
// TODO revert
// Cannot revoke tokens from auth server, no clientId available
// const token = await session.getAccessToken();
// try {
// await this._githubServer.revokeToken(token);
// } catch (_) {
// // ignore, should still remove from keychain
// }
}
await this.storeSessions();

View File

@@ -4,11 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import * as https from 'https';
import * as nls from 'vscode-nls';
import * as vscode from 'vscode';
import * as uuid from 'uuid';
import { PromiseAdapter, promiseFromEvent } from './common/utils';
import Logger from './common/logger';
import ClientRegistrar, { ClientDetails } from './common/clientRegistrar';
import ClientRegistrar from './common/clientRegistrar';
const localize = nls.loadMessageBundle();
export const NETWORK_ERROR = 'network error';
const AUTH_RELAY_SERVER = 'vscode-auth.github.com';
class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler {
public handleUri(uri: vscode.Uri) {
@@ -18,8 +24,8 @@ class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.
export const uriHandler = new UriEventHandler;
const exchangeCodeForToken: (state: string, clientDetails: ClientDetails) => PromiseAdapter<vscode.Uri, string> =
(state, clientDetails) => async (uri, resolve, reject) => {
const exchangeCodeForToken: (state: string, host: string, getPath: (code: string) => string) => PromiseAdapter<vscode.Uri, string> =
(state, host, getPath) => async (uri, resolve, reject) => {
Logger.info('Exchanging code for token...');
const query = parseQuery(uri);
const code = query.code;
@@ -30,8 +36,8 @@ const exchangeCodeForToken: (state: string, clientDetails: ClientDetails) => Pro
}
const post = https.request({
host: 'github.com',
path: `/login/oauth/access_token?client_id=${clientDetails.id}&client_secret=${clientDetails.secret}&state=${query.state}&code=${code}`,
host: host,
path: getPath(code),
method: 'POST',
headers: {
Accept: 'application/json'
@@ -67,15 +73,61 @@ function parseQuery(uri: vscode.Uri) {
}
export class GitHubServer {
private _statusBarItem: vscode.StatusBarItem | undefined;
public async login(scopes: string): Promise<string> {
Logger.info('Logging in...');
this.updateStatusBarItem(true);
const state = uuid();
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`));
const clientDetails = scopes === 'vso' ? ClientRegistrar.getGitHubAppDetails() : ClientRegistrar.getClientDetails(callbackUri);
const uri = vscode.Uri.parse(`https://github.com/login/oauth/authorize?redirect_uri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&client_id=${clientDetails.id}`);
let uri = vscode.Uri.parse(`https://${AUTH_RELAY_SERVER}/authorize/?callbackUri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&responseType=code`);
if (scopes === 'vso') {
const clientDetails = ClientRegistrar.getGitHubAppDetails();
uri = vscode.Uri.parse(`https://github.com/login/oauth/authorize?redirect_uri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&client_id=${clientDetails.id}`);
}
vscode.env.openExternal(uri);
return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, clientDetails));
return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state,
scopes === 'vso' ? 'github.com' : AUTH_RELAY_SERVER,
(code) => {
if (scopes === 'vso') {
const clientDetails = ClientRegistrar.getGitHubAppDetails();
return `/login/oauth/access_token?client_id=${clientDetails.id}&client_secret=${clientDetails.secret}&state=${state}&code=${code}`;
} else {
return `/token?code=${code}&state=${state}`;
}
})).finally(() => {
this.updateStatusBarItem(false);
});
}
private updateStatusBarItem(isStart?: boolean) {
if (isStart && !this._statusBarItem) {
this._statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
this._statusBarItem.text = localize('signingIn', "$(mark-github) Signing in to github.com...");
this._statusBarItem.command = 'github.provide-token';
this._statusBarItem.show();
}
if (!isStart && this._statusBarItem) {
this._statusBarItem.dispose();
this._statusBarItem = undefined;
}
}
public async manuallyProvideToken() {
const uriOrToken = await vscode.window.showInputBox({ prompt: 'Token', ignoreFocusOut: true });
if (!uriOrToken) { return; }
try {
const uri = vscode.Uri.parse(uriOrToken);
if (!uri.scheme || uri.scheme === 'file') { throw new Error; }
uriHandler.handleUri(uri);
} catch (e) {
Logger.error(e);
vscode.window.showErrorMessage(localize('unexpectedInput', "The input did not matched the expected format"));
}
}
public async hasUserInstallation(token: string): Promise<boolean> {
@@ -120,7 +172,7 @@ export class GitHubServer {
const uri = vscode.Uri.parse(`https://github.com/apps/microsoft-visual-studio-code/installations/new?state=${state}`);
vscode.env.openExternal(uri);
return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, clientDetails));
return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, 'github.com', (code) => `/login/oauth/access_token?client_id=${clientDetails.id}&client_secret=${clientDetails.secret}&state=${state}&code=${code}`));
}
public async getUserInfo(token: string): Promise<{ id: string, accountName: string }> {
@@ -145,7 +197,7 @@ export class GitHubServer {
Logger.info('Got account info!');
resolve({ id: json.id, accountName: json.login });
} else {
Logger.error('Getting account info failed');
Logger.error(`Getting account info failed: ${result.statusMessage}`);
reject(new Error(result.statusMessage));
}
});
@@ -153,7 +205,52 @@ export class GitHubServer {
post.end();
post.on('error', err => {
reject(err);
Logger.error(err.message);
reject(new Error(NETWORK_ERROR));
});
});
}
public async validateToken(token: string): Promise<void> {
return new Promise(async (resolve, reject) => {
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`));
const clientDetails = ClientRegistrar.getClientDetails(callbackUri);
const detailsString = `${clientDetails.id}:${clientDetails.secret}`;
const payload = JSON.stringify({ access_token: token });
Logger.info('Validating token...');
const post = https.request({
host: 'api.github.com',
path: `/applications/${clientDetails.id}/token`,
method: 'POST',
headers: {
Authorization: `Basic ${Buffer.from(detailsString).toString('base64')}`,
'User-Agent': 'Visual-Studio-Code',
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload)
}
}, result => {
const buffer: Buffer[] = [];
result.on('data', (chunk: Buffer) => {
buffer.push(chunk);
});
result.on('end', () => {
if (result.statusCode === 200) {
Logger.info('Validated token!');
resolve();
} else {
Logger.info(`Validating token failed: ${result.statusMessage}`);
reject(new Error(result.statusMessage));
}
});
});
post.write(payload);
post.end();
post.on('error', err => {
Logger.error(err.message);
reject(new Error(NETWORK_ERROR));
});
});
}

View File

@@ -24,7 +24,7 @@ export function activate(context: vscode.ExtensionContext) {
const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry);
context.subscriptions.push(vscode.window.registerCustomEditorProvider2(PreviewManager.viewType, previewManager, {
supportsMultipleEditorsPerResource: true,
supportsMultipleEditorsPerDocument: true,
}));
context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => {

View File

@@ -13,7 +13,7 @@ import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry';
const localize = nls.loadMessageBundle();
export class PreviewManager implements vscode.CustomEditorProvider {
export class PreviewManager implements vscode.CustomReadonlyEditorProvider {
public static readonly viewType = 'imagePreview.previewEditor';

View File

@@ -120,10 +120,10 @@
]
},
"dependencies": {
"request-light": "^0.2.5",
"request-light": "^0.3.0",
"vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^6.1.1",
"vscode-nls": "^4.1.1"
"vscode-languageclient": "^6.1.3",
"vscode-nls": "^4.1.2"
},
"devDependencies": {
"@types/node": "^12.11.7"

View File

@@ -23,6 +23,7 @@ The server implements the following capabilities of the language server protocol
- [Code Formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting) supporting ranges and formatting the whole document.
- [Folding Ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange) for all folding ranges in the document.
- Semantic Selection for semantic selection for one or multiple cursor positions.
- [Goto Definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) for $ref references in JSON schemas
- [Diagnostics (Validation)](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics) are pushed for all open documents
- syntax errors
- structural validation based on the document's [JSON schema](http://json-schema.org/).

View File

@@ -13,8 +13,8 @@
"main": "./out/jsonServerMain",
"dependencies": {
"jsonc-parser": "^2.2.1",
"request-light": "^0.2.5",
"vscode-json-languageservice": "^3.5.2",
"request-light": "^0.3.0",
"vscode-json-languageservice": "^3.6.0",
"vscode-languageserver": "^6.1.1",
"vscode-uri": "^2.1.1"
},

View File

@@ -174,7 +174,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
documentRangeFormattingProvider: params.initializationOptions.provideFormatter === true,
colorProvider: {},
foldingRangeProvider: true,
selectionRangeProvider: true
selectionRangeProvider: true,
definitionProvider: true
};
return { capabilities };
@@ -516,5 +517,16 @@ connection.onSelectionRanges((params, token) => {
}, [], `Error while computing selection ranges for ${params.textDocument.uri}`, token);
});
connection.onDefinition((params, token) => {
return runSafeAsync(async () => {
const document = documents.get(params.textDocument.uri);
if (document) {
const jsonDocument = getJSONDocument(document);
return languageService.findDefinition(document, params.position, jsonDocument);
}
return [];
}, [], `Error while computing definitions for ${params.textDocument.uri}`, token);
});
// Listen on the connection
connection.listen();

View File

@@ -53,7 +53,7 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
https-proxy-agent@^2.2.3:
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
@@ -71,24 +71,24 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
request-light@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
request-light@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.3.0.tgz#04daa783e7f0a70392328dda4b546f3e27845f2d"
integrity sha512-xlVlZVT0ZvCT+c3zm3SjeFCzchoQxsUUmx5fkal0I6RIDJK+lmb1UYyKJ7WM4dTfnzHP4ElWwAf8Dli8c0/tVA==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.3"
https-proxy-agent "^2.2.4"
vscode-nls "^4.1.1"
vscode-json-languageservice@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.5.2.tgz#4b898140a8e581359c10660845a4cae15dcbb4f9"
integrity sha512-9cUvBq00O08lpWVVOx6tQ1yLxCHss79nsUdEAVYGomRyMbnPBmc0AkYPcXI9WK1EM6HBo0R9Zo3NjFhcICpy4A==
vscode-json-languageservice@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.6.0.tgz#133a1e2c3a3dffe38564a1ba948516805c3c1869"
integrity sha512-dXzFywypUZ9T0tjr4fREZiknXDz6vAGx1zsxbQY1+9DOpjMfbz0VLP873KmcbuvL4K3nseKTxc4TKHu8kLXRMw==
dependencies:
jsonc-parser "^2.2.1"
vscode-languageserver-textdocument "^1.0.1"
vscode-languageserver-types "^3.15.1"
vscode-nls "^4.1.1"
vscode-nls "^4.1.2"
vscode-uri "^2.1.1"
vscode-jsonrpc@^5.0.1:
@@ -126,6 +126,11 @@ vscode-nls@^4.1.1:
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
vscode-nls@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
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

@@ -76,7 +76,7 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
https-proxy-agent@^2.2.3:
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
@@ -94,13 +94,13 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
request-light@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
request-light@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.3.0.tgz#04daa783e7f0a70392328dda4b546f3e27845f2d"
integrity sha512-xlVlZVT0ZvCT+c3zm3SjeFCzchoQxsUUmx5fkal0I6RIDJK+lmb1UYyKJ7WM4dTfnzHP4ElWwAf8Dli8c0/tVA==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.3"
https-proxy-agent "^2.2.4"
vscode-nls "^4.1.1"
semver@^5.3.0:
@@ -125,10 +125,10 @@ vscode-jsonrpc@^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.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.1.1.tgz#91b62e416c5abbf2013ae3726f314a19c22a8457"
integrity sha512-mB6d8Tg+82l8EFUfR+SBu0+lCshyKVgC5E5+MQ0/BJa+9AgeBjtG5npoGaCo4/VvWzK0ZRGm85zU5iRp1RYPIA==
vscode-languageclient@^6.1.3:
version "6.1.3"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz#c979c5bb5855714a0307e998c18ca827c1b3953a"
integrity sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==
dependencies:
semver "^6.3.0"
vscode-languageserver-protocol "^3.15.3"
@@ -151,6 +151,11 @@ vscode-nls@^4.1.1:
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
vscode-nls@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
zone.js@0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"

View File

@@ -313,7 +313,7 @@
"customEditors": [
{
"viewType": "vscode.markdown.preview.editor",
"displayName": "(Experimental) VS Code Markdown Preview",
"displayName": "Markdown Preview (Experimental)",
"priority": "option",
"selector": [
{

View File

@@ -104,7 +104,7 @@
"variable.other.enummember"
],
"settings": {
"foreground": "#D4D4D4",
"foreground": "#51B6C4",
}
},
{

View File

@@ -104,7 +104,7 @@
"variable.other.enummember"
],
"settings": {
"foreground": "#000000",
"foreground": "#328267",
}
},
{

View File

@@ -17,18 +17,6 @@
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "microsoft.signin",
"title": "%signIn%",
"category": "%displayName%"
},
{
"command": "microsoft.signout",
"title": "%signOut%",
"category": "%displayName%"
}
],
"configuration": {
"title": "Microsoft Account",
"properties": {

View File

@@ -5,11 +5,8 @@
import * as vscode from 'vscode';
import { AzureActiveDirectoryService, onDidChangeSessions } from './AADHelper';
import * as nls from 'vscode-nls';
import TelemetryReporter from 'vscode-extension-telemetry';
const localize = nls.loadMessageBundle();
export const DEFAULT_SCOPES = 'https://management.core.windows.net/.default offline_access';
export async function activate(context: vscode.ExtensionContext) {
@@ -48,39 +45,6 @@ export async function activate(context: vscode.ExtensionContext) {
}
}));
context.subscriptions.push(vscode.commands.registerCommand('microsoft.signin', () => {
return loginService.login(DEFAULT_SCOPES);
}));
context.subscriptions.push(vscode.commands.registerCommand('microsoft.signout', async () => {
const sessions = loginService.sessions;
if (sessions.length === 0) {
return;
}
if (sessions.length === 1) {
const id = loginService.sessions[0].id;
await loginService.logout(id);
onDidChangeSessions.fire({ added: [], removed: [id], changed: [] });
vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out."));
return;
}
const selectedSession = await vscode.window.showQuickPick(sessions.map(session => {
return {
id: session.id,
label: session.account.displayName
};
}));
if (selectedSession) {
await loginService.logout(selectedSession.id);
onDidChangeSessions.fire({ added: [], removed: [selectedSession.id], changed: [] });
vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out."));
return;
}
}));
return;
}

View File

@@ -1,2 +0,0 @@
out
node_modules

View File

@@ -1,17 +0,0 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["${workspaceFolder}/../../", "${workspaceFolder}/test", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
}
]
}

View File

@@ -1,11 +0,0 @@
{
"version": "2.0.0",
"command": "npm",
"type": "shell",
"presentation": {
"reveal": "silent"
},
"args": ["run", "compile"],
"isBackground": true,
"problemMatcher": "$tsc-watch"
}

View File

@@ -1,59 +0,0 @@
{
"name": "vscode-colorize-tests",
"description": "Colorize tests for VS Code",
"version": "0.0.1",
"publisher": "vscode",
"license": "MIT",
"private": true,
"activationEvents": [
"onLanguage:json"
],
"main": "./out/colorizerTestMain",
"enableProposedApi": true,
"engines": {
"vscode": "*"
},
"scripts": {
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json"
},
"dependencies": {
"jsonc-parser": "2.2.1"
},
"devDependencies": {
"@types/node": "^12.11.7",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"vscode": "1.1.5"
},
"contributes": {
"semanticTokenTypes": [
{
"id": "testToken",
"description": "A test token"
}
],
"semanticTokenModifiers": [
{
"id": "testModifier",
"description": "A test modifier"
}
],
"semanticTokenScopes": [
{
"scopes": {
"testToken": [
"entity.name.function.special"
]
}
}
],
"productIconThemes": [
{
"id": "Test Product Icons",
"label": "The Test Product Icon Theme",
"path": "./producticons/test-product-icon-theme.json",
"_watch": true
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) <2013> <Elegant Themes, Inc.>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,43 +0,0 @@
{
// ElegantIcons from https://www.elegantthemes.com/icons/elegant_font.zip
"fonts": [
{
"id": "elegant",
"src": [
{
"path": "./ElegantIcons.woff",
"format": "woff"
}
],
"weight": "normal",
"style": "normal",
}
],
"iconDefinitions": {
"chevron-down": {
"fontCharacter": "\\43",
},
"chevron-right": {
"fontCharacter": "\\45"
},
"error": {
"fontCharacter": "\\e062"
},
"warning": {
"fontCharacter": "\\e063"
},
"settings-gear": {
"fontCharacter": "\\e030"
},
"files": {
"fontCharacter": "\\e056"
},
"extensions": {
"fontCharacter": "\\e015"
},
"debug-alt-2": {
"fontCharacter": "\\e072"
}
}
}

View File

@@ -1,76 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import * as assert from 'assert';
import { commands, Uri } from 'vscode';
import { join, basename, normalize, dirname } from 'path';
import * as fs from 'fs';
function assertUnchangedTokens(testFixurePath: string, done: any) {
let fileName = basename(testFixurePath);
return commands.executeCommand('_workbench.captureSyntaxTokens', Uri.file(testFixurePath)).then(data => {
try {
let resultsFolderPath = join(dirname(dirname(testFixurePath)), 'colorize-results');
if (!fs.existsSync(resultsFolderPath)) {
fs.mkdirSync(resultsFolderPath);
}
let resultPath = join(resultsFolderPath, fileName.replace('.', '_') + '.json');
if (fs.existsSync(resultPath)) {
let previousData = JSON.parse(fs.readFileSync(resultPath).toString());
try {
assert.deepEqual(data, previousData);
} catch (e) {
fs.writeFileSync(resultPath, JSON.stringify(data, null, '\t'), { flag: 'w' });
if (Array.isArray(data) && Array.isArray(previousData) && data.length === previousData.length) {
for (let i= 0; i < data.length; i++) {
let d = data[i];
let p = previousData[i];
if (d.c !== p.c || hasThemeChange(d.r, p.r)) {
throw e;
}
}
// different but no tokenization ot color change: no failure
} else {
throw e;
}
}
} else {
fs.writeFileSync(resultPath, JSON.stringify(data, null, '\t'));
}
done();
} catch (e) {
done(e);
}
}, done);
}
function hasThemeChange(d: any, p: any) : boolean {
let keys = Object.keys(d);
for (let key of keys) {
if (d[key] !== p[key]) {
return true;
}
}
return false;
}
suite('colorization', () => {
let extensionsFolder = normalize(join(__dirname, '../../'));
let extensions = fs.readdirSync(extensionsFolder);
extensions.forEach(extension => {
let extensionColorizeFixturePath = join(extensionsFolder, extension, 'test', 'colorize-fixtures');
if (fs.existsSync(extensionColorizeFixturePath)) {
let fixturesFiles = fs.readdirSync(extensionColorizeFixturePath);
fixturesFiles.forEach(fixturesFile => {
// define a test for each fixture
test(extension + '-' + fixturesFile, function (done) {
assertUnchangedTokens(join(extensionColorizeFixturePath, fixturesFile), done);
});
});
}
});
});

View File

@@ -1,66 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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';
import * as jsoncParser from 'jsonc-parser';
export function activate(context: vscode.ExtensionContext): any {
const tokenTypes = ['type', 'struct', 'class', 'interface', 'enum', 'parameterType', 'function', 'variable', 'testToken'];
const tokenModifiers = ['static', 'abstract', 'deprecated', 'declaration', 'documentation', 'member', 'async', 'testModifier'];
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
const outputChannel = vscode.window.createOutputChannel('Semantic Tokens Test');
const documentSemanticHighlightProvider: vscode.DocumentSemanticTokensProvider = {
provideDocumentSemanticTokens(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticTokens> {
const builder = new vscode.SemanticTokensBuilder();
function addToken(value: string, startLine: number, startCharacter: number, length: number) {
const [type, ...modifiers] = value.split('.');
let tokenType = legend.tokenTypes.indexOf(type);
if (tokenType === -1) {
return;
}
let tokenModifiers = 0;
for (let i = 0; i < modifiers.length; i++) {
const index = legend.tokenModifiers.indexOf(modifiers[i]);
if (index !== -1) {
tokenModifiers = tokenModifiers | 1 << index;
}
}
builder.push(startLine, startCharacter, length, tokenType, tokenModifiers);
const selectedModifiers = legend.tokenModifiers.filter((_val, bit) => tokenModifiers & (1 << bit)).join(' ');
outputChannel.appendLine(`line: ${startLine}, character: ${startCharacter}, length ${length}, ${legend.tokenTypes[tokenType]} (${tokenType}), ${selectedModifiers} ${tokenModifiers.toString(2)}`);
}
outputChannel.appendLine('---');
const visitor: jsoncParser.JSONVisitor = {
onObjectProperty: (property: string, _offset: number, _length: number, startLine: number, startCharacter: number) => {
addToken(property, startLine, startCharacter, property.length + 2);
},
onLiteralValue: (value: any, _offset: number, length: number, startLine: number, startCharacter: number) => {
if (typeof value === 'string') {
addToken(value, startLine, startCharacter, length);
}
}
};
jsoncParser.visit(document.getText(), visitor);
return builder.build();
}
};
context.subscriptions.push(vscode.languages.registerDocumentSemanticTokensProvider({ pattern: '**/*semantic-test.json' }, documentSemanticHighlightProvider, legend));
}

View File

@@ -1,30 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path = require('path');
const testRunner = require('vscode/lib/testrunner');
const suite = 'Integration Colorize Tests';
const options: any = {
ui: 'tdd',
useColors: (!process.env.BUILD_ARTIFACTSTAGINGDIRECTORY && process.platform !== 'win32'),
timeout: 60000
};
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
options.reporter = 'mocha-multi-reporters';
options.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
}
testRunner.configure(options);
export = testRunner;

View File

@@ -1,9 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path="../../../../src/vs/vscode.d.ts" />
/// <reference path="../../../../src/vs/vscode.proposed.d.ts" />
/// <reference types='@types/node'/>

View File

@@ -1,13 +0,0 @@
{
"editor.tokenColorCustomizationsExperimental": {
"class": "#00b0b0",
"interface": "#845faf",
"function": "#ff00ff",
"*.declaration": {
"fontStyle": "underline"
},
"*.declaration.member": {
"fontStyle": "italic bold",
}
}
}

View File

@@ -1,9 +0,0 @@
[
"class", "function.member.declaration",
"parameterType.declaration", "type", "parameterType.declaration", "type",
"variable.declaration", "parameterNames",
"function.member.declaration",
"interface.declaration",
"function.member.declaration", "testToken.testModifier"
]

View File

@@ -1,9 +0,0 @@
{
"extends": "../shared.tsconfig.json",
"compilerOptions": {
"outDir": "./out"
},
"include": [
"src/**/*"
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -62,11 +62,10 @@
"keytar": "^5.5.0",
"minimist": "^1.2.5",
"native-is-elevated": "0.4.1",
"native-keymap": "2.1.1",
"native-keymap": "2.1.2",
"native-watchdog": "1.3.0",
"ng2-charts": "^1.6.0",
"node-pty": "0.10.0-beta8",
"onigasm-umd": "2.2.5",
"plotly.js-dist-min": "^1.53.0",
"reflect-metadata": "^0.1.8",
"rxjs": "5.4.0",
@@ -77,15 +76,16 @@
"sudo-prompt": "9.1.1",
"v8-inspect-profiler": "^0.0.20",
"vscode-nsfw": "1.2.8",
"vscode-oniguruma": "1.3.0",
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8",
"vscode-sqlite3": "4.0.10",
"vscode-textmate": "4.4.0",
"xterm": "4.6.0-beta.15",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.6",
"xterm-addon-webgl": "0.7.0-beta.8",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
"zone.js": "^0.8.4"
@@ -172,7 +172,7 @@
"opn": "^6.0.0",
"optimist": "0.3.5",
"p-all": "^1.0.0",
"playwright": "0.12.1",
"playwright": "0.15.0",
"pump": "^1.0.1",
"queue": "3.0.6",
"rcedit": "^1.1.0",
@@ -183,7 +183,7 @@
"temp-write": "^3.4.0",
"ts-loader": "^4.4.2",
"typemoq": "^0.3.2",
"typescript": "^3.9.0-dev.20200420",
"typescript": "^3.9.0-dev.20200427",
"typescript-formatter": "7.1.0",
"underscore": "^1.8.2",
"vinyl": "^2.0.0",

View File

@@ -60,6 +60,7 @@
]
},
"extensionAllowedProposedApi": [
"ms-vscode.vscode-js-profile-table",
"ms-vscode.references-view"
],
"extensionsGallery": {

View File

@@ -27,7 +27,6 @@
"native-watchdog": "1.3.0",
"ng2-charts": "^1.6.0",
"node-pty": "0.10.0-beta8",
"onigasm-umd": "2.2.5",
"reflect-metadata": "^0.1.8",
"rxjs": "5.4.0",
"sanitize-html": "^1.19.1",
@@ -35,14 +34,15 @@
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"spdlog": "^0.11.1",
"vscode-nsfw": "1.2.8",
"vscode-oniguruma": "1.3.0",
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8",
"vscode-textmate": "4.4.0",
"xterm": "4.6.0-beta.15",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.6",
"xterm-addon-webgl": "0.7.0-beta.8",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
"zone.js": "^0.8.4"

View File

@@ -2,32 +2,32 @@
"name": "vscode-web",
"version": "0.0.0",
"dependencies": {
"@angular/animations": "~4.1.3",
"@angular/common": "~4.1.3",
"@angular/compiler": "~4.1.3",
"@angular/core": "~4.1.3",
"@angular/forms": "~4.1.3",
"@angular/platform-browser": "~4.1.3",
"@angular/platform-browser-dynamic": "~4.1.3",
"@angular/router": "~4.1.3",
"angular2-grid": "2.0.6",
"ansi_up": "^3.0.0",
"chart.js": "^2.6.0",
"html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.6",
"jquery": "3.4.0",
"ng2-charts": "^1.6.0",
"onigasm-umd": "2.2.5",
"reflect-metadata": "^0.1.8",
"rxjs": "5.4.0",
"sanitize-html": "^1.19.1",
"@angular/animations": "~4.1.3",
"@angular/common": "~4.1.3",
"@angular/compiler": "~4.1.3",
"@angular/core": "~4.1.3",
"@angular/forms": "~4.1.3",
"@angular/platform-browser": "~4.1.3",
"@angular/platform-browser-dynamic": "~4.1.3",
"@angular/router": "~4.1.3",
"angular2-grid": "2.0.6",
"ansi_up": "^3.0.0",
"chart.js": "^2.6.0",
"html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.6",
"jquery": "3.4.0",
"ng2-charts": "^1.6.0",
"reflect-metadata": "^0.1.8",
"rxjs": "5.4.0",
"sanitize-html": "^1.19.1",
"semver-umd": "^5.5.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"vscode-textmate": "4.4.0",
"xterm": "4.6.0-beta.15",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"vscode-oniguruma": "1.3.0",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.6",
"zone.js": "^0.8.4"
"xterm-addon-webgl": "0.7.0-beta.8",
"zone.js": "^0.8.4"
}
}

View File

@@ -222,11 +222,6 @@ moment@^2.10.2:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
nan@^2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
ng2-charts@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/ng2-charts/-/ng2-charts-1.6.0.tgz#108a2133ff62a8623895240fadbddbea2951f29d"
@@ -239,18 +234,6 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
onigasm-umd@2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.5.tgz#f104247334a543accd3f8d641a4d99b3d908d6a1"
integrity sha512-R3qD7hq6i2bBklF+QyjqZl/G4fe7GwtukI28YLH2vuiatqx52tb9vpg2sxwemKc3nF76SgkeyOKJLchBmTm0Aw==
oniguruma@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/oniguruma/-/oniguruma-7.2.0.tgz#c9a59c1ea7b9fe67e237a02e02139b638856f3af"
integrity sha512-bh+ZLdykY1sdIx8jBp2zpLbVFDBc3XmKH4Ceo2lijNaN1WhEqtnpqFlmtCbRuDB17nJ58RAUStVwfW8e8uEbnA==
dependencies:
nan "^2.14.0"
postcss@^7.0.5:
version "7.0.21"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17"
@@ -355,12 +338,15 @@ util-deprecate@^1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
vscode-textmate@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.4.0.tgz#14032afeb50152e8f53258c95643e555f2948305"
integrity sha512-dFpm2eK0HwEjeFSD1DDh3j0q47bDSVuZt20RiJWxGqjtm73Wu2jip3C2KaZI3dQx/fSeeXCr/uEN4LNaNj7Ytw==
dependencies:
oniguruma "^7.2.0"
vscode-oniguruma@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
vscode-textmate@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.1.1.tgz#d88dbf271bee7cede455a21bd4894ba5724a4a7e"
integrity sha512-5VHjF+Fglf9d2JI5OyQ7FHutK6/29G0qYyD920K0SWO7uY8JTWbqyKAHEtfB/ZDk2fOe/E23n3wz9fHXKi63yg==
xtend@^4.0.1:
version "4.0.2"
@@ -382,15 +368,15 @@ xterm-addon-web-links@0.3.0:
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-webgl@0.7.0-beta.6:
version "0.7.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.6.tgz#340d728bae7456a1d67a7cb8996dfd51d96721b0"
integrity sha512-IoR0hPtG5qBrcLG1B7GSzo4W2hYocP8UgG5LlyXkEkT/0BqVcGnICgR8Ck7EfMmU8ci4jNFiHYjK/Bgc4m2S4g==
xterm-addon-webgl@0.7.0-beta.8:
version "0.7.0-beta.8"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.8.tgz#546651958d740bf05d6a05555fbcacd2759b2ee7"
integrity sha512-2jxMtRR5zgAar1gPqt0iD/+GOlZ3cHyzzbIbC77EBIdZZFuhEDhJkucVPPS2KPcyqw3VROL1FgX7BSEV2rvdeA==
xterm@4.6.0-beta.15:
version "4.6.0-beta.15"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.15.tgz#93a0cb1ff047a452b03070499e2ccd0ba53e0678"
integrity sha512-5G+3QSM/GKN/Tdq/IIU7FDivzh0eXsv3sNmZFDdtvNggnu2K56l4N5P0KZo0HdFztDfTyW/FLfqsPAwhrK4Khg==
xterm@4.6.0-beta.25:
version "4.6.0-beta.25"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.25.tgz#2faea6cf8c677ed545792562165604ce7f314026"
integrity sha512-63FLAUdJ8Bw9SMgLU3/r353P1WAtLxupbfvfddi4nMcz1WEGRq07O1CbmJn/bKHHkJw7gQQw0n1I8xnjFlLlTA==
zone.js@^0.8.4:
version "0.8.29"

View File

@@ -515,18 +515,6 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
onigasm-umd@2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.5.tgz#f104247334a543accd3f8d641a4d99b3d908d6a1"
integrity sha512-R3qD7hq6i2bBklF+QyjqZl/G4fe7GwtukI28YLH2vuiatqx52tb9vpg2sxwemKc3nF76SgkeyOKJLchBmTm0Aw==
oniguruma@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/oniguruma/-/oniguruma-7.2.0.tgz#c9a59c1ea7b9fe67e237a02e02139b638856f3af"
integrity sha512-bh+ZLdykY1sdIx8jBp2zpLbVFDBc3XmKH4Ceo2lijNaN1WhEqtnpqFlmtCbRuDB17nJ58RAUStVwfW8e8uEbnA==
dependencies:
nan "^2.14.0"
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@@ -710,6 +698,11 @@ vscode-nsfw@1.2.8:
lodash.isundefined "^3.0.1"
nan "^2.10.0"
vscode-oniguruma@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
vscode-proxy-agent@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/vscode-proxy-agent/-/vscode-proxy-agent-0.5.2.tgz#0c90d24d353957b841d741da7b2701e3f0a044c4"
@@ -725,12 +718,10 @@ vscode-ripgrep@^1.5.8:
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.8.tgz#32cb33da6d1a9ca8f5de8c2813ed5114fd55fc11"
integrity sha512-l6Pv/t1Jk63RU+kEkMO04XxnNRYdyzuesizj9AzFpcfrUxxpAjEJBK1qO9Mov30UUGZl7uDUBn+uCv9koaHPPA==
vscode-textmate@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.4.0.tgz#14032afeb50152e8f53258c95643e555f2948305"
integrity sha512-dFpm2eK0HwEjeFSD1DDh3j0q47bDSVuZt20RiJWxGqjtm73Wu2jip3C2KaZI3dQx/fSeeXCr/uEN4LNaNj7Ytw==
dependencies:
oniguruma "^7.2.0"
vscode-textmate@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.1.1.tgz#d88dbf271bee7cede455a21bd4894ba5724a4a7e"
integrity sha512-5VHjF+Fglf9d2JI5OyQ7FHutK6/29G0qYyD920K0SWO7uY8JTWbqyKAHEtfB/ZDk2fOe/E23n3wz9fHXKi63yg==
vscode-windows-ca-certs@0.2.0:
version "0.2.0"
@@ -764,15 +755,15 @@ xterm-addon-web-links@0.3.0:
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-webgl@0.7.0-beta.6:
version "0.7.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.6.tgz#340d728bae7456a1d67a7cb8996dfd51d96721b0"
integrity sha512-IoR0hPtG5qBrcLG1B7GSzo4W2hYocP8UgG5LlyXkEkT/0BqVcGnICgR8Ck7EfMmU8ci4jNFiHYjK/Bgc4m2S4g==
xterm-addon-webgl@0.7.0-beta.8:
version "0.7.0-beta.8"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.8.tgz#546651958d740bf05d6a05555fbcacd2759b2ee7"
integrity sha512-2jxMtRR5zgAar1gPqt0iD/+GOlZ3cHyzzbIbC77EBIdZZFuhEDhJkucVPPS2KPcyqw3VROL1FgX7BSEV2rvdeA==
xterm@4.6.0-beta.15:
version "4.6.0-beta.15"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.15.tgz#93a0cb1ff047a452b03070499e2ccd0ba53e0678"
integrity sha512-5G+3QSM/GKN/Tdq/IIU7FDivzh0eXsv3sNmZFDdtvNggnu2K56l4N5P0KZo0HdFztDfTyW/FLfqsPAwhrK4Khg==
xterm@4.6.0-beta.25:
version "4.6.0-beta.25"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.25.tgz#2faea6cf8c677ed545792562165604ce7f314026"
integrity sha512-63FLAUdJ8Bw9SMgLU3/r353P1WAtLxupbfvfddi4nMcz1WEGRq07O1CbmJn/bKHHkJw7gQQw0n1I8xnjFlLlTA==
yauzl@^2.9.2:
version "2.10.0"

View File

@@ -30,7 +30,6 @@ if not exist out yarn compile
set ELECTRON_RUN_AS_NODE=1
set NODE_ENV=development
set VSCODE_DEV=1
set ELECTRON_ENABLE_SECURITY_WARNINGS=1
REM set ELECTRON_DEFAULT_ERROR_MODE=1 TODO@ben to investigate if this helps with builds reporting stacks if renderer crashes
set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1

View File

@@ -39,7 +39,6 @@ function code() {
ELECTRON_RUN_AS_NODE=1 \
NODE_ENV=development \
VSCODE_DEV=1 \
ELECTRON_ENABLE_SECURITY_WARNINGS=1 \
ELECTRON_ENABLE_LOGGING=1 \
ELECTRON_ENABLE_STACK_DUMPING=1 \
"$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@"

View File

@@ -28,7 +28,6 @@ if not exist out yarn compile
:: Configuration
set NODE_ENV=development
set VSCODE_DEV=1
set ELECTRON_ENABLE_SECURITY_WARNINGS=1
set VSCODE_CLI=1
REM set ELECTRON_DEFAULT_ERROR_MODE=1 TODO@ben to investigate if this helps with builds reporting stacks if renderer crashes
set ELECTRON_ENABLE_LOGGING=1

View File

@@ -44,7 +44,6 @@ function code() {
# Configuration
export NODE_ENV=development
export VSCODE_DEV=1
export ELECTRON_ENABLE_SECURITY_WARNINGS=1
export VSCODE_CLI=1
export ELECTRON_ENABLE_STACK_DUMPING=1
export ELECTRON_ENABLE_LOGGING=1

View File

@@ -25,6 +25,7 @@ else
# and the build bundles extensions into .build webpacked
yarn gulp compile-extension:vscode-api-tests \
compile-extension:vscode-colorize-tests \
compile-extension:vscode-notebook-tests \
compile-extension:markdown-language-features \
compile-extension:emmet \
compile-extension:css-language-features-server \
@@ -44,14 +45,15 @@ fi
./scripts/test.sh --runGlob **/*.integrationTest.js "$@"
# Tests in the extension host
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/azurecore/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --skip-getting-started --user-data-dir=$VSCODEUSERDATADIR
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/azurecore/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# Tests in commonJS
cd $ROOT/extensions/css-language-features/server && $ROOT/scripts/node-electron.sh test/index.js

View File

@@ -10,4 +10,4 @@
.monaco-scroll-split-view {
height: 100%;
width: 100%;
}
}

View File

@@ -67,7 +67,7 @@ export interface IInsightData {
export interface IInsightsView {
data: IInsightData;
setConfig?: (config: { [key: string]: any }) => void;
setConfig?: (config: any) => void;
init?: () => void;
}

View File

@@ -10,7 +10,7 @@ import { ModelViewInput } from 'sql/workbench/browser/modelComponents/modelViewI
import { ModelViewEditor } from 'sql/workbench/browser/modelComponents/modelViewEditor';
// Model View editor registration
const viewModelEditorDescriptor = new EditorDescriptor(
const viewModelEditorDescriptor = EditorDescriptor.create(
ModelViewEditor,
ModelViewEditor.ID,
'ViewModel'

View File

@@ -4,72 +4,67 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, Disposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IAction, IActionViewItem, ActionRunner, Action } from 'vs/base/common/actions';
import { IAction, ActionRunner } from 'vs/base/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
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, IViewDescriptorService } from 'vs/workbench/common/views';
import { IMenuService, MenuId, MenuItemAction, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { ContextAwareMenuEntryActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IContextKeyService, ContextKeyExpr, ContextKeyEqualsExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, IViewsRegistry, ITreeItemLabel, Extensions, IViewDescriptorService, ViewContainer, ViewContainerLocation } 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';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import * as DOM from 'vs/base/browser/dom';
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { URI } from 'vs/base/common/uri';
import { dirname, basename } from 'vs/base/common/resources';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon, IThemeService } from 'vs/platform/theme/common/themeService';
import { FileKind } from 'vs/platform/files/common/files';
import { WorkbenchAsyncDataTree, TreeResourceNavigator } from 'vs/platform/list/browser/listService';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { localize } from 'vs/nls';
import { timeout } from 'vs/base/common/async';
import { editorFindMatchHighlight, editorFindMatchHighlightBorder, textLinkForeground, textCodeBlockBackground, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { textLinkForeground, textCodeBlockBackground, focusBorder, listFilterMatchHighlight, listFilterMatchHighlightBorder } from 'vs/platform/theme/common/colorRegistry';
import { isString } from 'vs/base/common/types';
import { renderMarkdown, MarkdownRenderOptions } from 'vs/base/browser/markdownRenderer';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IMarkdownRenderResult } from 'vs/editor/contrib/markdown/markdownRenderer';
import { ILabelService } from 'vs/platform/label/common/label';
import { Registry } from 'vs/platform/registry/common/platform';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { ITreeRenderer, ITreeNode, IAsyncDataSource, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree';
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults';
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
import { SIDE_BAR_BACKGROUND, PANEL_BACKGROUND } from 'vs/workbench/common/theme';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { firstIndex } from 'vs/base/common/arrays';
import { ITreeItem, ITreeView } from 'sql/workbench/common/views';
import { UserCancelledConnectionError } from 'sql/base/common/errors';
import { IOEShimService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerViewTreeShim';
import { NodeContextKey } from 'sql/workbench/browser/parts/views/nodeContext';
import { UserCancelledConnectionError } from 'sql/base/common/errors';
import { firstIndex } from 'vs/base/common/arrays';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
export class CustomTreeViewPane extends ViewPane {
export class TreeViewPane extends ViewPane {
private treeView: ITreeView;
constructor(
options: IViewletViewOptions,
@INotificationService private readonly notificationService: INotificationService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IOpenerService protected openerService: IOpenerService,
@IThemeService protected themeService: IThemeService,
@IInstantiationService instantiationService: IInstantiationService,
@IOpenerService openerService: IOpenerService,
@IThemeService themeService: IThemeService,
@ITelemetryService telemetryService: ITelemetryService,
) {
super({ ...(options as IViewPaneOptions) }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
super({ ...(options as IViewPaneOptions), titleMenuId: MenuId.ViewTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
this.treeView = treeView as ITreeView;
this._register(this.treeView.onDidChangeActions(() => this.updateActions(), this));
@@ -86,23 +81,22 @@ export class CustomTreeViewPane extends ViewPane {
}
renderBody(container: HTMLElement): void {
if (this.treeView instanceof CustomTreeView) {
super.renderBody(container);
if (this.treeView instanceof TreeView) {
this.treeView.show(container);
}
}
shouldShowWelcome(): boolean {
return (this.treeView.dataProvider === undefined) && (this.treeView.message === undefined);
return ((this.treeView.dataProvider === undefined) || !!this.treeView.dataProvider.isTreeEmpty) && (this.treeView.message === undefined);
}
layoutBody(height: number, width: number): void {
super.layoutBody(height, width);
this.treeView.layout(height, width);
}
getActionViewItem(action: IAction): IActionViewItem | undefined {
return action instanceof MenuItemAction ? new ContextAwareMenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService) : undefined;
}
getOptimalWidth(): number {
return this.treeView.getOptimalWidth();
}
@@ -112,51 +106,6 @@ export class CustomTreeViewPane extends ViewPane {
}
}
class TitleMenus extends Disposable {
private titleActions: IAction[] = [];
private readonly titleActionsDisposable = this._register(new MutableDisposable());
private titleSecondaryActions: IAction[] = [];
private _onDidChangeTitle = this._register(new Emitter<void>());
readonly onDidChangeTitle: Event<void> = this._onDidChangeTitle.event;
constructor(
id: string,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
) {
super();
const scopedContextKeyService = this._register(this.contextKeyService.createScoped());
scopedContextKeyService.createKey('view', id);
const titleMenu = this._register(this.menuService.createMenu(MenuId.ViewTitle, scopedContextKeyService));
const updateActions = () => {
this.titleActions = [];
this.titleSecondaryActions = [];
this.titleActionsDisposable.value = createAndFillInActionBarActions(titleMenu, undefined, { primary: this.titleActions, secondary: this.titleSecondaryActions });
this._onDidChangeTitle.fire();
};
this._register(titleMenu.onDidChange(updateActions));
updateActions();
this._register(toDisposable(() => {
this.titleActions = [];
this.titleSecondaryActions = [];
}));
}
getTitleActions(): IAction[] {
return this.titleActions;
}
getTitleSecondaryActions(): IAction[] {
return this.titleSecondaryActions;
}
}
class Root implements ITreeItem {
label = { label: 'root' };
handle = '0';
@@ -167,29 +116,30 @@ class Root implements ITreeItem {
const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");
export class CustomTreeView extends Disposable implements ITreeView {
class Tree extends WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore> { }
export class TreeView extends Disposable implements ITreeView {
private isVisible: boolean = false;
private activated: boolean = false;
private _hasIconForParentNode = false;
private _hasIconForLeafNode = false;
private _showCollapseAllAction = false;
private readonly collapseAllContextKey: RawContextKey<boolean>;
private readonly collapseAllContext: IContextKey<boolean>;
private readonly refreshContextKey: RawContextKey<boolean>;
private readonly refreshContext: IContextKey<boolean>;
private focused: boolean = false;
private domNode: HTMLElement;
private treeContainer: HTMLElement;
private _messageValue: string | IMarkdownString | undefined;
private domNode!: HTMLElement;
private treeContainer!: HTMLElement;
private _messageValue: string | undefined;
private _canSelectMany: boolean = false;
private messageElement: HTMLDivElement;
private tree: WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore>;
private treeLabels: ResourceLabels;
private messageElement!: HTMLDivElement;
private tree: Tree | undefined;
private treeLabels: ResourceLabels | undefined;
private root: ITreeItem;
private elementsToRefresh: ITreeItem[] = [];
private menus: TitleMenus;
private markdownRenderer: MarkdownRenderer;
private markdownResult: IMarkdownRenderResult | null;
private readonly _onDidExpandItem: Emitter<ITreeItem> = this._register(new Emitter<ITreeItem>());
readonly onDidExpandItem: Event<ITreeItem> = this._onDidExpandItem.event;
@@ -212,69 +162,111 @@ export class CustomTreeView extends Disposable implements ITreeView {
private readonly _onDidChangeTitle: Emitter<string> = this._register(new Emitter<string>());
readonly onDidChangeTitle: Event<string> = this._onDidChangeTitle.event;
private readonly _onDidCompleteRefresh: Emitter<void> = this._register(new Emitter<void>());
private nodeContext: NodeContextKey;
constructor(
private id: string,
protected readonly id: string,
private _title: string,
private viewContainer: ViewContainer,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
@IThemeService private readonly themeService: IThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ICommandService private readonly commandService: ICommandService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProgressService private readonly progressService: IProgressService,
@IProgressService protected readonly progressService: IProgressService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IKeybindingService private readonly keybindingService: IKeybindingService
@IKeybindingService private readonly keybindingService: IKeybindingService,
@INotificationService private readonly notificationService: INotificationService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super();
this.root = new Root();
this.menus = this._register(instantiationService.createInstance(TitleMenus, this.id));
this._register(this.menus.onDidChangeTitle(() => this._onDidChangeActions.fire()));
this.collapseAllContextKey = new RawContextKey<boolean>(`treeView.${this.id}.enableCollapseAll`, false);
this.collapseAllContext = this.collapseAllContextKey.bindTo(contextKeyService);
this.refreshContextKey = new RawContextKey<boolean>(`treeView.${this.id}.enableRefresh`, false);
this.refreshContext = this.refreshContextKey.bindTo(contextKeyService);
this._register(this.themeService.onDidFileIconThemeChange(() => this.doRefresh([this.root]) /** soft refresh **/));
this._register(this.themeService.onDidColorThemeChange(() => this.doRefresh([this.root]) /** soft refresh **/));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('explorer.decorations')) {
this.doRefresh([this.root]).catch(onUnexpectedError); /** soft refresh **/
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.doRefresh([this.root]); /** soft refresh **/
}
}));
this.markdownRenderer = instantiationService.createInstance(MarkdownRenderer);
this._register(toDisposable(() => {
if (this.markdownResult) {
this.markdownResult.dispose();
}
}));
this._register(Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).onDidChangeContainer(({ views, from, to }) => {
if (from === this.viewContainer && views.some(v => v.id === this.id)) {
this.viewContainer = to;
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
if (views.some(v => v.id === this.id)) {
this.tree?.updateOptions({ overrideStyles: { listBackground: this.viewLocation === ViewContainerLocation.Sidebar ? SIDE_BAR_BACKGROUND : PANEL_BACKGROUND } });
}
}));
this.registerActions();
this.nodeContext = this._register(instantiationService.createInstance(NodeContextKey));
this.nodeContext = this._register(instantiationService.createInstance(NodeContextKey)); // tracked change
this.create();
}
private _dataProvider: ITreeViewDataProvider | null;
get dataProvider(): ITreeViewDataProvider | null {
collapse(element: ITreeItem): boolean {
if (this.tree) {
return this.tree.collapse(element);
}
return false;
}
get viewContainer(): ViewContainer {
return this.viewDescriptorService.getViewContainerByViewId(this.id)!;
}
get viewLocation(): ViewContainerLocation {
return this.viewDescriptorService.getViewLocationById(this.id)!;
}
private _dataProvider: ITreeViewDataProvider | undefined;
get dataProvider(): ITreeViewDataProvider | undefined {
return this._dataProvider;
}
set dataProvider(dataProvider: ITreeViewDataProvider | null) {
set dataProvider(dataProvider: ITreeViewDataProvider | undefined) {
if (this.tree === undefined) {
this.createTree();
}
if (dataProvider) {
this._dataProvider = new class implements ITreeViewDataProvider {
private _isEmpty: boolean = true;
private _onDidChangeEmpty: Emitter<void> = new Emitter();
public onDidChangeEmpty: Event<void> = this._onDidChangeEmpty.event;
get isTreeEmpty(): boolean {
return this._isEmpty;
}
async getChildren(node: ITreeItem): Promise<ITreeItem[]> {
let children: ITreeItem[];
if (node && node.children) {
return Promise.resolve(node.children);
children = node.children;
} else {
children = await (node instanceof Root ? dataProvider.getChildren() : dataProvider.getChildren(node));
node.children = children;
}
if (node instanceof Root) {
const oldEmpty = this._isEmpty;
this._isEmpty = children.length === 0;
if (oldEmpty !== this._isEmpty) {
this._onDidChangeEmpty.fire();
}
}
const children = await (node instanceof Root ? dataProvider.getChildren() : dataProvider.getChildren(node));
node.children = children;
return children;
}
};
if (this._dataProvider.onDidChangeEmpty) {
this._register(this._dataProvider.onDidChangeEmpty(() => this._onDidChangeWelcomeState.fire()));
}
this.updateMessage();
this.refresh().catch(onUnexpectedError);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.refresh();
} else {
this._dataProvider = null;
this._dataProvider = undefined;
this.updateMessage();
}
@@ -322,27 +314,61 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
get showCollapseAllAction(): boolean {
return this._showCollapseAllAction;
return !!this.collapseAllContext.get();
}
set showCollapseAllAction(showCollapseAllAction: boolean) {
if (this._showCollapseAllAction !== !!showCollapseAllAction) {
this._showCollapseAllAction = !!showCollapseAllAction;
this._onDidChangeActions.fire();
}
this.collapseAllContext.set(showCollapseAllAction);
}
getPrimaryActions(): IAction[] {
if (this.showCollapseAllAction) {
const collapseAllAction = new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action collapse-all', true, () => this.tree ? new CollapseAllAction<ITreeItem, ITreeItem, FuzzyScore>(this.tree, true).run() : Promise.resolve());
return [...this.menus.getTitleActions(), collapseAllAction];
} else {
return this.menus.getTitleActions();
}
get showRefreshAction(): boolean {
return !!this.refreshContext.get();
}
getSecondaryActions(): IAction[] {
return this.menus.getTitleSecondaryActions();
set showRefreshAction(showRefreshAction: boolean) {
this.refreshContext.set(showRefreshAction);
}
private registerActions() {
const that = this;
this._register(registerAction2(class extends Action2 {
constructor() {
super({
id: `workbench.actions.treeView.${that.id}.refresh`,
title: localize('refresh', "Refresh"),
menu: {
id: MenuId.ViewTitle,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', that.id), that.refreshContextKey),
group: 'navigation',
order: Number.MAX_SAFE_INTEGER - 1,
},
icon: { id: 'codicon/refresh' }
});
}
async run(): Promise<void> {
return that.refresh();
}
}));
this._register(registerAction2(class extends Action2 {
constructor() {
super({
id: `workbench.actions.treeView.${that.id}.collapseAll`,
title: localize('collapseAll', "Collapse All"),
menu: {
id: MenuId.ViewTitle,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', that.id), that.collapseAllContextKey),
group: 'navigation',
order: Number.MAX_SAFE_INTEGER,
},
icon: { id: 'codicon/collapse-all' }
});
}
async run(): Promise<void> {
if (that.tree) {
return new CollapseAllAction<ITreeItem, ITreeItem, FuzzyScore>(that.tree, true).run();
}
}
}));
}
setVisibility(isVisible: boolean): void {
@@ -352,9 +378,6 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
this.isVisible = isVisible;
if (this.isVisible) {
this.activate();
}
if (this.tree) {
if (this.isVisible) {
@@ -364,7 +387,8 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
if (this.isVisible && this.elementsToRefresh.length) {
this.doRefresh(this.elementsToRefresh).catch(onUnexpectedError);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.doRefresh(this.elementsToRefresh);
this.elementsToRefresh = [];
}
}
@@ -372,16 +396,18 @@ export class CustomTreeView extends Disposable implements ITreeView {
this._onDidChangeVisibility.fire(this.isVisible);
}
focus(): void {
focus(reveal: boolean = true): void {
if (this.tree && this.root.children && this.root.children.length > 0) {
// Make sure the current selected element is revealed
const selectedElement = this.tree.getSelection()[0];
if (selectedElement) {
if (selectedElement && reveal) {
this.tree.reveal(selectedElement, 0.5);
}
// Pass Focus to Viewer
this.tree.domFocus();
} else if (this.tree) {
this.tree.domFocus();
} else {
this.domNode.focus();
}
@@ -406,18 +432,21 @@ export class CustomTreeView extends Disposable implements ITreeView {
const actionViewItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuEntryActionViewItem, action) : undefined;
const treeMenus = this._register(this.instantiationService.createInstance(TreeMenus, this.id));
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.id, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.viewContainer.id }, () => task));
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.id, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.id }, () => task));
const aligner = new Aligner(this.themeService);
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner);
const widgetAriaLabel = this._title;
this.tree = this._register(this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'SqlCustomView', this.treeContainer, new CustomTreeDelegate(), [renderer],
this.tree = this._register(this.instantiationService.createInstance(Tree, this.id, this.treeContainer, new TreeViewDelegate(), [renderer],
dataSource, {
identityProvider: new CustomViewIdentityProvider(),
identityProvider: new TreeViewIdentityProvider(),
accessibilityProvider: {
getAriaLabel(element: ITreeItem): string {
return element.label ? element.label.label : '';
return element.tooltip ? element.tooltip : element.label ? element.label.label : '';
},
getWidgetAriaLabel: () => this.title
getWidgetAriaLabel(): string {
return widgetAriaLabel;
}
},
keyboardNavigationLabelProvider: {
getKeyboardNavigationLabel: (item: ITreeItem) => {
@@ -429,15 +458,22 @@ export class CustomTreeView extends Disposable implements ITreeView {
return e.collapsibleState !== TreeItemCollapsibleState.Expanded;
},
multipleSelectionSupport: this.canSelectMany,
overrideStyles: {
listBackground: this.viewLocation === ViewContainerLocation.Sidebar ? SIDE_BAR_BACKGROUND : PANEL_BACKGROUND
}
}) as WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore>);
aligner.tree = this.tree;
const actionRunner = new MultipleSelectionActionRunner(() => this.tree!.getSelection());
const actionRunner = new MultipleSelectionActionRunner(this.notificationService, () => this.tree!.getSelection());
renderer.actionRunner = actionRunner;
this.tree.contextKeyService.createKey<boolean>(this.id, true);
this._register(this.tree.onContextMenu(e => this.onContextMenu(treeMenus, e, actionRunner)));
this._register(this.tree.onDidChangeSelection(e => this._onDidChangeSelection.fire(e.elements)));
this._register(this.tree.onDidChangeCollapseState(e => {
if (!e.node.element) {
return;
}
const element: ITreeItem = Array.isArray(e.node.element.element) ? e.node.element.element[0] : e.node.element.element;
if (e.node.collapsed) {
this._onDidCollapseItem.fire(element);
@@ -446,18 +482,18 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
}));
// Update resource context based on focused element
this._register(this.tree.onDidChangeFocus(e => {
this._register(this.tree.onDidChangeFocus(e => { // tracked change
this.nodeContext.set({ node: e.elements[0], viewId: this.id });
}));
this.tree.setInput(this.root).then(() => this.updateContentAreas());
const customTreeNavigator = new TreeResourceNavigator(this.tree, { openOnFocus: false, openOnSelection: false });
this._register(customTreeNavigator);
this._register(customTreeNavigator.onDidOpenResource(e => {
const treeNavigator = new TreeResourceNavigator(this.tree, { openOnFocus: false, openOnSelection: false });
this._register(treeNavigator);
this._register(treeNavigator.onDidOpenResource(e => {
if (!e.browserEvent) {
return;
}
const selection = this.tree.getSelection();
const selection = this.tree!.getSelection();
if ((selection.length === 1) && selection[0].command) {
this.commandService.executeCommand(selection[0].command.id, ...(selection[0].command.arguments || []));
}
@@ -474,7 +510,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
event.preventDefault();
event.stopPropagation();
this.tree.setFocus([node]);
this.tree!.setFocus([node]);
const actions = treeMenus.getResourceContextActions(node);
if (!actions.length) {
return;
@@ -494,17 +530,17 @@ export class CustomTreeView extends Disposable implements ITreeView {
onHide: (wasCancelled?: boolean) => {
if (wasCancelled) {
this.tree.domFocus();
this.tree!.domFocus();
}
},
getActionsContext: () => (<TreeViewItemHandleArg>{ $treeViewId: this.id, $treeItemHandle: node.handle, $treeItem: node, $treeContainerId: this.treeContainer.id }),
getActionsContext: () => (<TreeViewItemHandleArg>{ $treeViewId: this.id, $treeItemHandle: node.handle }),
actionRunner
});
}
private updateMessage(): void {
protected updateMessage(): void {
if (this._message) {
this.showMessage(this._message);
} else if (!this.dataProvider) {
@@ -515,43 +551,36 @@ export class CustomTreeView extends Disposable implements ITreeView {
this.updateContentAreas();
}
private showMessage(message: string | IMarkdownString): void {
private showMessage(message: string): void {
DOM.removeClass(this.messageElement, 'hide');
if (this._messageValue !== message) {
this.resetMessageElement();
this._messageValue = message;
if (isString(this._messageValue)) {
this.messageElement.textContent = this._messageValue;
} else {
this.markdownResult = this.markdownRenderer.render(this._messageValue);
DOM.append(this.messageElement, this.markdownResult.element);
}
this.layout(this._size);
this.resetMessageElement();
this._messageValue = message;
if (!isFalsyOrWhitespace(this._message)) {
this.messageElement.textContent = this._messageValue;
}
this.layout(this._height, this._width);
}
private hideMessage(): void {
this.resetMessageElement();
DOM.addClass(this.messageElement, 'hide');
this.layout(this._size);
this.layout(this._height, this._width);
}
private resetMessageElement(): void {
if (this.markdownResult) {
this.markdownResult.dispose();
this.markdownResult = null;
}
DOM.clearNode(this.messageElement);
}
private _size: number;
layout(size: number) {
if (size) {
this._size = size;
const treeSize = size - DOM.getTotalHeight(this.messageElement);
this.treeContainer.style.height = treeSize + 'px';
private _height: number = 0;
private _width: number = 0;
layout(height: number, width: number) {
if (height && width) {
this._height = height;
this._width = width;
const treeHeight = height - DOM.getTotalHeight(this.messageElement);
this.treeContainer.style.height = treeHeight + 'px';
if (this.tree) {
this.tree.layout(treeSize);
this.tree.layout(treeHeight, width);
}
}
}
@@ -565,8 +594,11 @@ export class CustomTreeView extends Disposable implements ITreeView {
return 0;
}
refresh(elements?: ITreeItem[]): Promise<void> {
async refresh(elements?: ITreeItem[]): Promise<void> {
if (this.dataProvider && this.tree) {
if (this.refreshing) {
await Event.toPromise(this._onDidCompleteRefresh.event);
}
if (!elements) {
elements = [this.root];
// remove all waiting elements to refresh if root is asked to refresh
@@ -591,24 +623,17 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
}
}
return Promise.resolve(undefined);
}
collapse(element: ITreeItem): boolean {
if (this.tree) {
return this.tree.collapse(element);
}
return Promise.arguments(null);
return undefined;
}
async expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void> {
if (this.tree) {
const tree = this.tree;
if (tree) {
itemOrItems = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
await Promise.all(itemOrItems.map(element => {
return this.tree.expand(element, false);
return tree.expand(element, false);
}));
}
return Promise.resolve(undefined);
}
setSelection(items: ITreeItem[]): void {
@@ -624,34 +649,23 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
}
reveal(item: ITreeItem): Promise<void> {
async reveal(item: ITreeItem): Promise<void> {
if (this.tree) {
return Promise.resolve(this.tree.reveal(item));
}
return Promise.resolve();
}
private activate() {
if (!this.activated) {
this.createTree();
this.progressService.withProgress({ location: this.viewContainer.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
.then(() => timeout(2000))
.then(() => {
this.updateMessage();
});
this.activated = true;
return this.tree.reveal(item);
}
}
private refreshing: boolean = false;
private async doRefresh(elements: ITreeItem[]): Promise<void> {
if (this.tree) {
const tree = this.tree;
if (tree && this.visible) {
this.refreshing = true;
await Promise.all(elements.map(element => this.tree.updateChildren(element, true)));
await Promise.all(elements.map(element => tree.updateChildren(element, true, true)));
this.refreshing = false;
this._onDidCompleteRefresh.fire();
this.updateContentAreas();
if (this.focused) {
this.focus();
this.focus(false);
}
}
}
@@ -669,13 +683,13 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
}
class CustomViewIdentityProvider implements IIdentityProvider<ITreeItem> {
class TreeViewIdentityProvider implements IIdentityProvider<ITreeItem> {
getId(element: ITreeItem): { toString(): string; } {
return element.handle;
}
}
class CustomTreeDelegate implements IListVirtualDelegate<ITreeItem> {
class TreeViewDelegate implements IListVirtualDelegate<ITreeItem> {
getHeight(element: ITreeItem): number {
return TreeRenderer.ITEM_HEIGHT;
@@ -704,7 +718,7 @@ class TreeDataSource implements IAsyncDataSource<ITreeItem, ITreeItem> {
}
async getChildren(node: ITreeItem): Promise<any[]> {
if (node.childProvider) {
if (node.childProvider) { // tracked change
try {
return await this.withProgress(this.objectExplorerService.getChildren(node, this.id));
} catch (err) {
@@ -728,19 +742,18 @@ class TreeDataSource implements IAsyncDataSource<ITreeItem, ITreeItem> {
}
}
// todo@joh,sandy make this proper and contributable from extensions
registerThemingParticipant((theme, collector) => {
const findMatchHighlightColor = theme.getColor(editorFindMatchHighlight);
if (findMatchHighlightColor) {
collector.addRule(`.file-icon-themable-tree .monaco-list-row .content .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
const matchBackgroundColor = theme.getColor(listFilterMatchHighlight);
if (matchBackgroundColor) {
collector.addRule(`.file-icon-themable-tree .monaco-list-row .content .monaco-highlighted-label .highlight { color: unset !important; background-color: ${matchBackgroundColor}; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; background-color: ${matchBackgroundColor}; }`);
}
const findMatchHighlightColorBorder = theme.getColor(editorFindMatchHighlightBorder);
if (findMatchHighlightColorBorder) {
collector.addRule(`.file-icon-themable-tree .monaco-list-row .content .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
const matchBorderColor = theme.getColor(listFilterMatchHighlightBorder);
if (matchBorderColor) {
collector.addRule(`.file-icon-themable-tree .monaco-list-row .content .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${matchBorderColor}; box-sizing: border-box; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${matchBorderColor}; box-sizing: border-box; }`);
}
const link = theme.getColor(textLinkForeground);
if (link) {
@@ -776,7 +789,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
private labels: ResourceLabels,
private actionViewItemProvider: IActionViewItemProvider,
private aligner: Aligner,
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
@IThemeService private readonly themeService: IThemeService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService
) {
@@ -812,6 +825,23 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
const treeItemLabel: ITreeItemLabel | undefined = node.label ? node.label : resource ? { label: basename(resource) } : undefined;
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : undefined;
const label = treeItemLabel ? treeItemLabel.label : undefined;
const matches = (treeItemLabel && treeItemLabel.highlights && label) ? treeItemLabel.highlights.map(([start, end]) => {
if ((Math.abs(start) > label.length) || (Math.abs(end) >= label.length)) {
return ({ start: 0, end: 0 });
}
if (start < 0) {
start = label.length + start;
}
if (end < 0) {
end = label.length + end;
}
if (start > end) {
const swap = start;
start = end;
end = swap;
}
return ({ start, end });
}) : undefined;
const icon = this.themeService.getColorTheme().type === LIGHT ? node.icon : node.iconDark;
const iconUrl = icon ? URI.revive(icon) : null;
const title = node.tooltip ? node.tooltip : resource ? undefined : label;
@@ -820,18 +850,30 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
// reset
templateData.actionBar.clear();
if (resource || node.themeIcon) {
if (resource || this.isFileKindThemeIcon(node.themeIcon)) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: createMatches(element.filterData) });
templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: matches ? matches : createMatches(element.filterData) });
} else {
templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: createMatches(element.filterData) });
templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: matches ? matches : createMatches(element.filterData) });
}
templateData.icon.title = title ? title : '';
if (iconUrl || sqlIcon) {
DOM.toggleClass(templateData.icon, sqlIcon, !!sqlIcon); // tracked change
DOM.toggleClass(templateData.icon, 'icon', !!sqlIcon);
templateData.icon.className = 'custom-view-tree-node-item-icon';
templateData.icon.style.backgroundImage = iconUrl ? DOM.asCSSUrl(iconUrl) : '';
} else {
let iconClass: string | undefined;
if (node.themeIcon && !this.isFileKindThemeIcon(node.themeIcon)) {
iconClass = ThemeIcon.asClassName(node.themeIcon);
}
templateData.icon.className = iconClass ? `custom-view-tree-node-item-icon ${iconClass}` : '';
templateData.icon.style.backgroundImage = '';
}
templateData.icon.className = '';
templateData.icon.style.backgroundImage = iconUrl ? `url('${DOM.asDomUri(iconUrl).toString(true)}')` : '';
DOM.toggleClass(templateData.icon, sqlIcon, !!sqlIcon);
DOM.toggleClass(templateData.icon, 'icon', !!sqlIcon);
DOM.toggleClass(templateData.icon, 'custom-view-tree-node-item-icon', !!iconUrl || !!sqlIcon);
templateData.actionBar.context = <TreeViewItemHandleArg>{ $treeViewId: this.treeViewId, $treeItemHandle: node.handle };
templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false });
if (this._actionRunner) {
@@ -845,6 +887,14 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
DOM.toggleClass(container.parentElement!, 'align-icon-with-twisty', this.aligner.alignIconWithTwisty(treeItem));
}
private isFileKindThemeIcon(icon: ThemeIcon | undefined): boolean {
if (icon) {
return icon.id === FileThemeIcon.id || icon.id === FolderThemeIcon.id;
} else {
return false;
}
}
private getFileKind(node: ITreeItem): FileKind {
if (node.themeIcon) {
switch (node.themeIcon.id) {
@@ -869,9 +919,9 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
}
class Aligner extends Disposable {
private _tree: WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore>;
private _tree: WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore> | undefined;
constructor(private themeService: IWorkbenchThemeService) {
constructor(private themeService: IThemeService) {
super();
}
@@ -887,11 +937,15 @@ class Aligner extends Disposable {
return false;
}
const parent: ITreeItem = this._tree.getParentElement(treeItem) || this._tree.getInput();
if (this.hasIcon(parent)) {
if (this._tree) {
const parent: ITreeItem = this._tree.getParentElement(treeItem) || this._tree.getInput();
if (this.hasIcon(parent)) {
return false;
}
return !!parent.children && parent.children.every(c => c.collapsibleState === TreeItemCollapsibleState.None || !this.hasIcon(c));
} else {
return false;
}
return !!parent.children && parent.children.every(c => c.collapsibleState === TreeItemCollapsibleState.None || !this.hasIcon(c));
}
private hasIcon(node: ITreeItem): boolean {
@@ -913,22 +967,32 @@ class Aligner extends Disposable {
class MultipleSelectionActionRunner extends ActionRunner {
constructor(private getSelectedResources: (() => ITreeItem[])) {
constructor(notificationService: INotificationService, private getSelectedResources: (() => ITreeItem[])) {
super();
this._register(this.onDidRun(e => {
if (e.error) {
notificationService.error(localize('command-error', 'Error running command {1}: {0}. This is likely caused by the extension that contributes {1}.', e.error.message, e.action.id));
}
}));
}
runAction(action: IAction, context: TreeViewItemHandleArg): Promise<any> {
runAction(action: IAction, context: TreeViewItemHandleArg): Promise<void> {
const selection = this.getSelectedResources();
let selectionHandleArgs: TreeViewItemHandleArg[] | undefined = undefined;
let actionInSelected: boolean = false;
if (selection.length > 1) {
selectionHandleArgs = [];
selection.forEach(selected => {
if (selected.handle !== context.$treeItemHandle) {
selectionHandleArgs!.push({ $treeViewId: context.$treeViewId, $treeItemHandle: selected.handle });
selectionHandleArgs = selection.map(selected => {
if (selected.handle === context.$treeItemHandle) {
actionInSelected = true;
}
return { $treeViewId: context.$treeViewId, $treeItemHandle: selected.handle };
});
}
if (!actionInSelected) {
selectionHandleArgs = undefined;
}
return action.run(...[context, selectionHandleArgs]);
}
}
@@ -945,14 +1009,14 @@ class TreeMenus extends Disposable implements IDisposable {
}
getResourceActions(element: ITreeItem): IAction[] {
return this.mergeActions([
return this.mergeActions([ // tracked change
this.getActions(MenuId.ViewItemContext, { key: 'viewItem', value: element.contextValue }).primary,
this.getActions(MenuId.DataExplorerContext, { key: 'viewItem', value: element.contextValue }).primary
]);
}
getResourceContextActions(element: ITreeItem): IAction[] {
return this.mergeActions([
return this.mergeActions([ // tracked change
this.getActions(MenuId.ViewItemContext, { key: 'viewItem', value: element.contextValue }).secondary,
this.getActions(MenuId.DataExplorerContext, { key: 'viewItem', value: element.contextValue }).secondary
]);
@@ -962,7 +1026,7 @@ class TreeMenus extends Disposable implements IDisposable {
return actions.reduce((p, c) => p.concat(...c.filter(a => firstIndex(p, x => x.id === a.id) === -1)), [] as IAction[]);
}
private getActions(menuId: MenuId, context: { key: string, value: string }): { primary: IAction[]; secondary: IAction[]; } {
private getActions(menuId: MenuId, context: { key: string, value?: string }): { primary: IAction[]; secondary: IAction[]; } {
const contextKeyService = this.contextKeyService.createScoped();
contextKeyService.createKey('view', this.id);
contextKeyService.createKey(context.key, context.value);
@@ -980,38 +1044,43 @@ class TreeMenus extends Disposable implements IDisposable {
}
}
class MarkdownRenderer {
export class CustomTreeView extends TreeView {
private activated: boolean = false;
constructor(
@IOpenerService private readonly _openerService: IOpenerService
id: string,
title: string,
@IThemeService themeService: IThemeService,
@IInstantiationService instantiationService: IInstantiationService,
@ICommandService commandService: ICommandService,
@IConfigurationService configurationService: IConfigurationService,
@IProgressService progressService: IProgressService,
@IContextMenuService contextMenuService: IContextMenuService,
@IKeybindingService keybindingService: IKeybindingService,
@INotificationService notificationService: INotificationService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IContextKeyService contextKeyService: IContextKeyService,
@IExtensionService private readonly extensionService: IExtensionService,
) {
super(id, title, themeService, instantiationService, commandService, configurationService, progressService, contextMenuService, keybindingService, notificationService, viewDescriptorService, contextKeyService);
}
private getOptions(disposeables: DisposableStore): MarkdownRenderOptions {
return {
actionHandler: {
callback: (content) => {
let uri: URI | undefined;
try {
uri = URI.parse(content);
} catch {
// ignore
}
if (uri && this._openerService) {
this._openerService.open(uri).catch(onUnexpectedError);
}
},
disposeables
}
};
setVisibility(isVisible: boolean): void {
super.setVisibility(isVisible);
if (this.visible) {
this.activate();
}
}
render(markdown: IMarkdownString): IMarkdownRenderResult {
const disposeables = new DisposableStore();
const element: HTMLElement = markdown ? renderMarkdown(markdown, this.getOptions(disposeables)) : document.createElement('span');
return {
element,
dispose: () => disposeables.dispose()
};
private activate() {
if (!this.activated) {
this.progressService.withProgress({ location: this.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
.then(() => timeout(2000))
.then(() => {
this.updateMessage();
});
this.activated = true;
}
}
}

View File

@@ -32,7 +32,7 @@ export interface ITreeItem extends vsITreeItem {
export interface ITreeView extends vsITreeView {
collapse(itemOrItems: ITreeItem): boolean;
collapse(element: ITreeItem): boolean
}

View File

@@ -91,13 +91,13 @@ export class Insight {
private findctor(type: ChartType | InsightType): IInsightCtor {
if (find(Graph.types, x => x === type as ChartType)) {
return Graph;
return Graph as IInsightCtor;
} else if (find(ImageInsight.types, x => x === type as InsightType)) {
return ImageInsight;
return ImageInsight as IInsightCtor;
} else if (find(TableInsight.types, x => x === type as InsightType)) {
return TableInsight;
return TableInsight as IInsightCtor;
} else if (find(CountInsight.types, x => x === type as InsightType)) {
return CountInsight;
return CountInsight as IInsightCtor;
}
return undefined;
}

View File

@@ -8,6 +8,7 @@ import { mixin } from 'sql/base/common/objects';
import * as types from 'vs/base/common/types';
import { IInsightOptions, InsightType, ChartType } from 'sql/workbench/contrib/charts/common/interfaces';
import { IInsightData } from 'sql/platform/dashboard/browser/insightRegistry';
import { BrandedService } from 'vs/platform/instantiation/common/instantiation';
export interface IPointDataSet {
data: Array<{ x: number | string, y: number }>;
@@ -42,6 +43,6 @@ export interface IInsight {
}
export interface IInsightCtor {
new(container: HTMLElement, options: IInsightOptions, ...services: { _serviceBrand: undefined; }[]): IInsight;
new <Services extends BrandedService[]>(container: HTMLElement, options: IInsightOptions, ...services: Services): IInsight;
readonly types: Array<InsightType | ChartType>;
}

View File

@@ -48,7 +48,7 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
dashboardHelper.filterConfigs
];
private readonly _gridModifiers: Array<(item: Array<WidgetConfig>, originalConfig: Array<WidgetConfig>) => Array<WidgetConfig>> = [
private readonly _gridModifiers: Array<(item: Array<WidgetConfig>, originalConfig?: Array<WidgetConfig>) => Array<WidgetConfig>> = [
dashboardHelper.validateGridConfig
];

View File

@@ -12,7 +12,6 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo
import { WidgetConfig } from 'sql/workbench/contrib/dashboard/browser/core/dashboardWidget';
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/browser/insightRegistry';
import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';
import { DashboardServiceInterface } from 'sql/workbench/contrib/dashboard/browser/services/dashboardServiceInterface.service';
import { WIDGETS_CONTAINER } from 'sql/workbench/contrib/dashboard/browser/containers/dashboardWidgetContainer.contribution';
import { GRID_CONTAINER } from 'sql/workbench/contrib/dashboard/browser/containers/dashboardGridContainer.contribution';
import { WEBVIEW_CONTAINER } from 'sql/workbench/contrib/dashboard/browser/containers/dashboardWebviewContainer.contribution';
@@ -111,7 +110,7 @@ export function addProvider<T extends { connectionManagementService: SingleConne
* Adds the edition to the passed widgets and returns the new widgets
* @param widgets Array of widgets to add edition onto
*/
export function addEdition<T extends { connectionManagementService: SingleConnectionManagementService }>(config: WidgetConfig[], collection: DashboardServiceInterface): Array<WidgetConfig> {
export function addEdition<T extends { connectionManagementService: SingleConnectionManagementService }>(config: WidgetConfig[], collection: T): Array<WidgetConfig> {
const connectionInfo: ConnectionManagementInfo = collection.connectionManagementService.connectionInfo;
if (connectionInfo.serverInfo) {
const edition = connectionInfo.serverInfo.engineEditionId;

View File

@@ -107,7 +107,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
return this.dashboardService.scopedContextKeyService;
}
private readonly _gridModifiers: Array<(item: Array<WidgetConfig>, originalConfig: Array<WidgetConfig>) => Array<WidgetConfig>> = [
private readonly _gridModifiers: Array<(item: Array<WidgetConfig>, originalConfig?: Array<WidgetConfig>) => Array<WidgetConfig>> = [
dashboardHelper.validateGridConfig
];

View File

@@ -57,7 +57,7 @@ MenuRegistry.appendMenuItem(MenuId.ObjectExplorerItemContext, {
when: ContextKeyExpr.or(ContextKeyExpr.and(TreeNodeContextKey.Status.notEqualsTo('Unavailable'), TreeNodeContextKey.NodeType.isEqualTo('Server')), ContextKeyExpr.and(TreeNodeContextKey.Status.notEqualsTo('Unavailable'), TreeNodeContextKey.NodeType.isEqualTo('Database')))
});
const dashboardEditorDescriptor = new EditorDescriptor(
const dashboardEditorDescriptor = EditorDescriptor.create(
DashboardEditor,
DashboardEditor.ID,
localize('dashboard.editor.label', "Dashboard")

View File

@@ -7,16 +7,17 @@ import { localize } from 'vs/nls';
import { forEach } from 'vs/base/common/collections';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { Registry } from 'vs/platform/registry/common/platform';
import { IViewContainersRegistry, ViewContainer, Extensions as ViewContainerExtensions, ITreeViewDescriptor, IViewsRegistry } from 'vs/workbench/common/views';
import { IViewContainersRegistry, ViewContainer, Extensions as ViewContainerExtensions, IViewsRegistry } from 'vs/workbench/common/views';
import { IExtensionPoint, ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { coalesce } from 'vs/base/common/arrays';
import { CustomTreeViewPane, CustomTreeView } from 'sql/workbench/browser/parts/views/customView';
import { CustomTreeView, TreeViewPane } from 'sql/workbench/browser/parts/views/treeView';
import { VIEWLET_ID } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ICustomViewDescriptor } from 'vs/workbench/api/browser/viewsExtensionPoint';
interface IUserFriendlyViewDescriptor {
id: string;
@@ -103,14 +104,15 @@ export class DataExplorerContainerExtensionHandler implements IWorkbenchContribu
return null;
}
const viewDescriptor = <ITreeViewDescriptor>{
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctorDescriptor: new SyncDescriptor(CustomTreeViewPane),
ctorDescriptor: new SyncDescriptor(TreeViewPane),
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
canMoveView: true,
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name),
collapsed: this.showCollapsed(container),
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name, container),
extensionId: extension.description.identifier,
originalContainerId: entry.key
};

View File

@@ -12,7 +12,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
// Editor
const editDataEditorDescriptor = new EditorDescriptor(
const editDataEditorDescriptor = EditorDescriptor.create(
EditDataEditor,
EditDataEditor.ID,
'EditData'
@@ -22,7 +22,7 @@ Registry.as<IEditorRegistry>(Extensions.Editors)
.registerEditor(editDataEditorDescriptor, [new SyncDescriptor(EditDataInput)]);
// Editor
const editDataResultsEditorDescriptor = new EditorDescriptor(
const editDataResultsEditorDescriptor = EditorDescriptor.create(
EditDataResultsEditor,
EditDataResultsEditor.ID,
'EditDataResults'

View File

@@ -21,7 +21,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import * as queryContext from 'sql/workbench/contrib/query/common/queryContext';
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
import { IAction } from 'vs/base/common/actions';
import { IQueryModelService } from 'sql/workbench/services/query/common/queryModel';
import { IEditorDescriptorService } from 'sql/workbench/services/queryEditor/browser/editorDescriptorService';
import {
@@ -321,7 +321,7 @@ export class EditDataEditor extends BaseEditor {
// Create QueryTaskbar
this._taskbarContainer = DOM.append(parentElement, DOM.$('div'));
this._taskbar = new Taskbar(this._taskbarContainer, {
actionViewItemProvider: (action: Action) => this._getChangeMaxRowsAction(action)
actionViewItemProvider: (action: IAction) => this._getChangeMaxRowsAction(action)
});
// Create Actions for the toolbar
@@ -352,7 +352,7 @@ export class EditDataEditor extends BaseEditor {
/**
* Gets the IActionItem for the list of row number drop down
*/
private _getChangeMaxRowsAction(action: Action): IActionViewItem {
private _getChangeMaxRowsAction(action: IAction): IActionViewItem {
let actionID = ChangeMaxRowsAction.ID;
if (action.id === actionID) {
if (!this._changeMaxRowsActionItem) {

View File

@@ -25,8 +25,8 @@ export class ShowRecommendedExtensionsByScenarioAction extends Action {
run(): Promise<void> {
return this.viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet?.getViewPaneContainer())
.then((viewlet: IExtensionsViewPaneContainer) => {
.then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)
.then(viewlet => {
viewlet.search('@' + this.scenarioType);
viewlet.focus();
});
@@ -51,8 +51,8 @@ export class InstallRecommendedExtensionsByScenarioAction extends Action {
run(): Promise<any> {
if (!this.recommendations.length) { return Promise.resolve(); }
return this.viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet?.getViewPaneContainer())
.then((viewlet: IExtensionsViewPaneContainer) => {
.then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)
.then(viewlet => {
viewlet.search('@' + this.scenarioType);
viewlet.focus();
const names = this.recommendations.map(({ extensionId }) => extensionId);

View File

@@ -57,7 +57,7 @@ Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.Language
.registerLanguageAssociation(NotebookEditorInputAssociation.languages, NotebookEditorInputAssociation);
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
.registerEditor(new EditorDescriptor(NotebookEditor, NotebookEditor.ID, localize('notebookEditor.name', "Notebook Editor")), [new SyncDescriptor(UntitledNotebookInput), new SyncDescriptor(FileNotebookInput)]);
.registerEditor(EditorDescriptor.create(NotebookEditor, NotebookEditor.ID, localize('notebookEditor.name', "Notebook Editor")), [new SyncDescriptor(UntitledNotebookInput), new SyncDescriptor(FileNotebookInput)]);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(NotebookThemingContribution, LifecyclePhase.Restored);

View File

@@ -14,7 +14,7 @@ import { ProfilerInput } from 'sql/workbench/browser/editor/profiler/profilerInp
import { ProfilerEditor } from 'sql/workbench/contrib/profiler/browser/profilerEditor';
import { PROFILER_VIEW_TEMPLATE_SETTINGS, PROFILER_SESSION_TEMPLATE_SETTINGS, IProfilerViewTemplate, IProfilerSessionTemplate, EngineType, PROFILER_FILTER_SETTINGS } from 'sql/workbench/services/profiler/browser/interfaces';
const profilerDescriptor = new EditorDescriptor(
const profilerDescriptor = EditorDescriptor.create(
ProfilerEditor,
ProfilerEditor.ID,
'ProfilerEditor'

View File

@@ -395,7 +395,7 @@ export class ProfilerEditor extends BaseEditor {
this._detailTable.updateRowCount();
});
const detailTableCopyKeybind = new CopyKeybind();
const detailTableCopyKeybind = new CopyKeybind<IDetailData>();
detailTableCopyKeybind.onCopy((ranges: Slick.Range[]) => {
// we always only get 1 item in the ranges
if (ranges && ranges.length === 1) {

View File

@@ -323,7 +323,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
private table: Table<T>;
private actionBar: ActionBar;
private container = document.createElement('div');
private selectionModel = new CellSelectionModel();
private selectionModel = new CellSelectionModel<T>();
private styles: ITableStyles;
private currentHeight: number;
private dataProvider: AsyncDataProvider<T>;
@@ -461,7 +461,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
this.renderGridDataRowsRange(startIndex, count);
});
this.rowNumberColumn = new RowNumberColumn({ numberOfRows: this.resultSet.rowCount });
let copyHandler = new CopyKeybind();
let copyHandler = new CopyKeybind<T>();
copyHandler.onCopy(e => {
new CopyResultAction(CopyResultAction.COPY_ID, CopyResultAction.COPY_LABEL, false).run(this.generateContext());
});

View File

@@ -57,10 +57,10 @@ Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.Language
.registerLanguageAssociation(QueryEditorLanguageAssociation.languages, QueryEditorLanguageAssociation, QueryEditorLanguageAssociation.isDefault);
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
.registerEditor(new EditorDescriptor(QueryResultsEditor, QueryResultsEditor.ID, localize('queryResultsEditor.name', "Query Results")), [new SyncDescriptor(QueryResultsInput)]);
.registerEditor(EditorDescriptor.create(QueryResultsEditor, QueryResultsEditor.ID, localize('queryResultsEditor.name', "Query Results")), [new SyncDescriptor(QueryResultsInput)]);
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
.registerEditor(new EditorDescriptor(QueryEditor, QueryEditor.ID, localize('queryEditor.name', "Query Editor")), [new SyncDescriptor(FileQueryEditorInput), new SyncDescriptor(UntitledQueryEditorInput)]);
.registerEditor(EditorDescriptor.create(QueryEditor, QueryEditor.ID, localize('queryEditor.name', "Query Editor")), [new SyncDescriptor(FileQueryEditorInput), new SyncDescriptor(UntitledQueryEditorInput)]);
const actionRegistry = <IWorkbenchActionRegistry>Registry.as(ActionExtensions.WorkbenchActions);

View File

@@ -24,7 +24,7 @@ import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ISelectionData } from 'azdata';
import { Action, IActionViewItem } from 'vs/base/common/actions';
import { IActionViewItem, IAction } from 'vs/base/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
@@ -171,7 +171,7 @@ export class QueryEditor extends BaseEditor {
// Create QueryTaskbar
let taskbarContainer = DOM.append(parentElement, DOM.$('div'));
this.taskbar = this._register(new Taskbar(taskbarContainer, {
actionViewItemProvider: (action: Action) => this._getActionItemForAction(action),
actionViewItemProvider: action => this._getActionItemForAction(action),
}));
// Create Actions for the toolbar
@@ -236,7 +236,7 @@ export class QueryEditor extends BaseEditor {
* Gets the IActionItem for the List Databases dropdown if provided the associated Action.
* Otherwise returns null.
*/
private _getActionItemForAction(action: Action): IActionViewItem {
private _getActionItemForAction(action: IAction): IActionViewItem {
if (action.id === actions.ListDatabasesAction.ID) {
return this.listDatabasesActionItem;
}

View File

@@ -12,7 +12,7 @@ import { ILanguageAssociationRegistry, Extensions as LanguageAssociationExtensio
// Query Plan editor registration
const queryPlanEditorDescriptor = new EditorDescriptor(
const queryPlanEditorDescriptor = EditorDescriptor.create(
QueryPlanEditor,
QueryPlanEditor.ID,
'QueryPlan'

View File

@@ -48,7 +48,7 @@ export class StatusUpdater extends lifecycle.Disposable implements ext.IWorkbenc
lifecycle.dispose(this.badgeHandle);
let numOfInProgressTask: number = this.taskService.getNumberOfInProgressTasks();
let badge: NumberBadge = new NumberBadge(numOfInProgressTask, n => localize('inProgressTasksChangesBadge', "{0} in progress tasks", n));
this.badgeHandle = this.activityBarService.showActivity(TASKS_CONTAINER_ID, badge, 'taskhistory-viewlet-label');
this.badgeHandle = this.activityBarService.showViewContainerActivity(TASKS_CONTAINER_ID, { badge, clazz: 'taskhistory-viewlet-label' });
}
public getId(): string {

View File

@@ -46,6 +46,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { KeyCode } from 'vs/base/common/keyCodes';
import { joinPath } from 'vs/base/common/resources';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { addStandardDisposableListener, EventHelper } from 'vs/base/browser/dom';
const configurationKey = 'workbench.startupEditor';
const oldConfigurationKey = 'workbench.welcome.enabled';
@@ -321,23 +322,21 @@ class WelcomePage extends Disposable {
}
private createWidePreviewToolTip() {
const previewLink = document.querySelector('#tool_tip_container_wide');
const tooltip = document.querySelector('#tooltip_text_wide');
const previewLink = document.querySelector('#tool_tip_container_wide') as HTMLElement;
const tooltip = document.querySelector('#tooltip_text_wide') as HTMLElement;
const previewModalBody = document.querySelector('.preview_tooltip_body') as HTMLElement;
const previewModalHeader = document.querySelector('.preview_tooltip_header') as HTMLElement;
previewLink.addEventListener('mouseover', () => {
addStandardDisposableListener(previewLink, 'mouseover', () => {
tooltip.setAttribute('aria-hidden', 'true');
tooltip.classList.toggle('show');
});
previewLink.addEventListener('mouseout', () => {
addStandardDisposableListener(previewLink, 'mouseout', () => {
tooltip.setAttribute('aria-hidden', 'false');
tooltip.classList.remove('show');
});
previewLink.addEventListener('keydown', (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
addStandardDisposableListener(previewLink, 'keydown', event => {
if (event.equals(KeyCode.Escape)) {
if (tooltip.classList.contains('show')) {
tooltip.setAttribute('aria-hidden', 'true');
@@ -351,9 +350,7 @@ class WelcomePage extends Disposable {
}
});
tooltip.addEventListener('keydown', (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
addStandardDisposableListener(tooltip, 'keydown', event => {
if (event.equals(KeyCode.Escape)) {
if (tooltip.classList.contains('show')) {
tooltip.setAttribute('aria-hidden', 'true');
@@ -361,8 +358,8 @@ class WelcomePage extends Disposable {
}
}
else if (event.equals(KeyCode.Tab)) {
e.preventDefault();
if (e.target === previewModalBody) {
EventHelper.stop(event);
if (event.target === previewModalBody) {
previewModalHeader.focus();
} else {
previewModalBody.focus();
@@ -381,15 +378,14 @@ class WelcomePage extends Disposable {
}
private createDropDown() {
const dropdownBtn = document.querySelector('#dropdown_btn');
const dropdownBtn = document.querySelector('#dropdown_btn') as HTMLElement;
const dropdown = document.querySelector('#dropdown') as HTMLInputElement;
dropdownBtn.addEventListener('click', () => {
addStandardDisposableListener(dropdownBtn, 'click', () => {
dropdown.classList.toggle('show');
});
dropdownBtn.addEventListener('keydown', (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
addStandardDisposableListener(dropdownBtn, 'keydown', event => {
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
const dropdownFirstElement = document.querySelector('#dropdown').firstElementChild.children[0] as HTMLInputElement;
dropdown.classList.toggle('show');
@@ -397,8 +393,7 @@ class WelcomePage extends Disposable {
}
});
dropdown.addEventListener('keydown', (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
addStandardDisposableListener(dropdown, 'keydown', event => {
if (event.equals(KeyCode.Escape)) {
if (dropdown.classList.contains('show')) {
dropdown.classList.remove('show');
@@ -427,16 +422,15 @@ class WelcomePage extends Disposable {
}
});
dropdown.addEventListener('keydown', function (e: KeyboardEvent) {
addStandardDisposableListener(dropdown, 'keydown', event => {
const dropdownLastElement = document.querySelector('#dropdown').lastElementChild.children[0] as HTMLInputElement;
const dropdownFirstElement = document.querySelector('#dropdown').firstElementChild.children[0] as HTMLInputElement;
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Tab)) {
e.preventDefault();
EventHelper.stop(event);
return;
}
else if (event.equals(KeyCode.UpArrow) || event.equals(KeyCode.LeftArrow)) {
if (e.target === dropdownFirstElement) {
if (event.target === dropdownFirstElement) {
dropdownLastElement.focus();
} else {
const movePrev = <HTMLElement>document.querySelector('.move:focus').parentElement.previousElementSibling.children[0] as HTMLElement;
@@ -444,7 +438,7 @@ class WelcomePage extends Disposable {
}
}
else if (event.equals(KeyCode.DownArrow) || event.equals(KeyCode.RightArrow)) {
if (e.target === dropdownLastElement) {
if (event.target === dropdownLastElement) {
dropdownFirstElement.focus();
} else {
const moveNext = <HTMLElement>document.querySelector('.move:focus').parentElement.nextElementSibling.children[0] as HTMLElement;

View File

@@ -52,16 +52,16 @@ const labelDisplay = nls.localize("insights.item", "Item");
const valueDisplay = nls.localize("insights.value", "Value");
const iconClass = 'codicon';
class InsightTableView<T> extends ViewPane {
private _table: Table<T>;
public get table(): Table<T> {
class InsightTableView extends ViewPane {
private _table: Table<ListResource>;
public get table(): Table<ListResource> {
return this._table;
}
constructor(
private columns: Slick.Column<T>[],
private data: IDisposableDataProvider<T> | Array<T>,
private tableOptions: Slick.GridOptions<T>,
private columns: Slick.Column<ListResource>[],
private data: IDisposableDataProvider<ListResource> | Array<ListResource>,
private tableOptions: Slick.GridOptions<ListResource>,
options: IViewPaneOptions,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@@ -220,14 +220,14 @@ export class InsightsDialogView extends Modal {
const itemsHeaderTitle = nls.localize("insights.dialog.items", "Items");
const itemsDetailHeaderTitle = nls.localize("insights.dialog.itemDetails", "Item Details");
this._topTableData = new TableDataView();
this._bottomTableData = new TableDataView();
let topTableView = this._instantiationService.createInstance(InsightTableView, this._topColumns, this._topTableData, { forceFitColumns: true }, { id: 'insights.top', title: itemsHeaderTitle }) as InsightTableView<ListResource>;
this._topTableData = new TableDataView<ListResource>();
this._bottomTableData = new TableDataView<ListResource>();
let topTableView = this._instantiationService.createInstance(InsightTableView, this._topColumns, this._topTableData, { forceFitColumns: true }, { id: 'insights.top', title: itemsHeaderTitle });
topTableView.render();
attachPanelStyler(topTableView, this._themeService);
this._topTable = topTableView.table;
this._topTable.setSelectionModel(new RowSelectionModel<ListResource>());
let bottomTableView = this._instantiationService.createInstance(InsightTableView, this._bottomColumns, this._bottomTableData, { forceFitColumns: true }, { id: 'insights.bottom', title: itemsDetailHeaderTitle }) as InsightTableView<ListResource>;
let bottomTableView = this._instantiationService.createInstance(InsightTableView, this._bottomColumns, this._bottomTableData, { forceFitColumns: true }, { id: 'insights.bottom', title: itemsDetailHeaderTitle });
bottomTableView.render();
attachPanelStyler(bottomTableView, this._themeService);
this._bottomTable = bottomTableView.table;
@@ -275,8 +275,8 @@ export class InsightsDialogView extends Modal {
this._register(attachTableStyler(this._topTable, this._themeService));
this._register(attachTableStyler(this._bottomTable, this._themeService));
this._topTable.grid.onKeyDown.subscribe((e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
this._topTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
topTableView.focus();
e.stopImmediatePropagation();
@@ -286,8 +286,8 @@ export class InsightsDialogView extends Modal {
}
});
this._bottomTable.grid.onKeyDown.subscribe((e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
this._bottomTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
bottomTableView.focus();
e.stopImmediatePropagation();

View File

@@ -53,7 +53,7 @@ const languageAssociationRegistry = new class implements ILanguageAssociationReg
}
}
registerLanguageAssociation<Services extends BrandedService[]>(languages: string[], contribution: ILanguageAssociationSignature<Services>, isDefault?: boolean): IDisposable {
registerLanguageAssociation(languages: string[], contribution: ILanguageAssociationSignature<BrandedService[]>, isDefault?: boolean): IDisposable {
for (const language of languages) {
this.associationContructors.set(language, contribution);
}

View File

@@ -379,8 +379,8 @@ export class RestoreDialog extends Modal {
}
});
this._restorePlanTable.grid.onKeyDown.subscribe((e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
this._restorePlanTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
this._destinationRestoreToInputBox.isEnabled() ? this._destinationRestoreToInputBox.focus() : this._databaseDropdown.focus();
e.stopImmediatePropagation();
@@ -390,8 +390,8 @@ export class RestoreDialog extends Modal {
}
});
this._fileListTable.grid.onKeyDown.subscribe((e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
this._fileListTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
if ((<InputBox>this._optionsMap[this._relocatedLogFileFolderOption]).isEnabled()) {
(<InputBox>this._optionsMap[this._relocatedLogFileFolderOption]).focus();

View File

@@ -1554,7 +1554,7 @@ declare namespace Slick {
}
export interface Formatter<T extends SlickData> {
(row: number, cell: number, value: any, columnDef: Column<T>, dataContext: SlickData): string | undefined;
(row: number, cell: number, value: any, columnDef: Column<T>, dataContext: T): string | undefined;
}
export module Formatters {

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