mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 27ada910e121e23a6d95ecca9cae595fb98ab568
This commit is contained in:
@@ -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
Reference in New Issue
Block a user