mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 17:23:31 -05:00
Merge branch 'ads-master-vscode-2020-04-30T00-53-40'
This commit is contained in:
@@ -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
1
.vscode/launch.json
vendored
@@ -79,7 +79,6 @@
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch azuredatastudio",
|
||||
"browserLaunchLocation": "workspace",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat"
|
||||
},
|
||||
|
||||
22
.vscode/searches/ts36031.code-search
vendored
22
.vscode/searches/ts36031.code-search
vendored
@@ -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)!,
|
||||
|
||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -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",
|
||||
|
||||
@@ -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/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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}}
|
||||
];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
"language": "dockerfile",
|
||||
"scopeName": "source.dockerfile",
|
||||
"path": "./syntaxes/docker.tmLanguage.json"
|
||||
}]
|
||||
}],
|
||||
"configurationDefaults": {
|
||||
"[dockerfile]": {
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
|
||||
|
||||
13
extensions/git/src/api/git.d.ts
vendored
13
extensions/git/src/api/git.d.ts
vendored
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
66
extensions/git/src/github.ts
Normal file
66
extensions/git/src/github.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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()];
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
43
extensions/git/src/terminal.ts
Normal file
43
extensions/git/src/terminal.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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": {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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/).
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"customEditors": [
|
||||
{
|
||||
"viewType": "vscode.markdown.preview.editor",
|
||||
"displayName": "(Experimental) VS Code Markdown Preview",
|
||||
"displayName": "Markdown Preview (Experimental)",
|
||||
"priority": "option",
|
||||
"selector": [
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"variable.other.enummember"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#D4D4D4",
|
||||
"foreground": "#51B6C4",
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"variable.other.enummember"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#000000",
|
||||
"foreground": "#328267",
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
2
extensions/vscode-colorize-tests/.gitignore
vendored
2
extensions/vscode-colorize-tests/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
out
|
||||
node_modules
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"command": "npm",
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"args": ["run", "compile"],
|
||||
"isBackground": true,
|
||||
"problemMatcher": "$tsc-watch"
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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'/>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"editor.tokenColorCustomizationsExperimental": {
|
||||
"class": "#00b0b0",
|
||||
"interface": "#845faf",
|
||||
"function": "#ff00ff",
|
||||
"*.declaration": {
|
||||
"fontStyle": "underline"
|
||||
},
|
||||
"*.declaration.member": {
|
||||
"fontStyle": "italic bold",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
]
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "../shared.tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -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",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
]
|
||||
},
|
||||
"extensionAllowedProposedApi": [
|
||||
"ms-vscode.vscode-js-profile-table",
|
||||
"ms-vscode.references-view"
|
||||
],
|
||||
"extensionsGallery": {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" . "$@"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
.monaco-scroll-split-view {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export interface IInsightData {
|
||||
|
||||
export interface IInsightsView {
|
||||
data: IInsightData;
|
||||
setConfig?: (config: { [key: string]: any }) => void;
|
||||
setConfig?: (config: any) => void;
|
||||
init?: () => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export interface ITreeItem extends vsITreeItem {
|
||||
|
||||
export interface ITreeView extends vsITreeView {
|
||||
|
||||
collapse(itemOrItems: ITreeItem): boolean;
|
||||
collapse(element: ITreeItem): boolean
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
2
src/typings/slickgrid.d.ts
vendored
2
src/typings/slickgrid.d.ts
vendored
@@ -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
Reference in New Issue
Block a user