Clean up some of the extensions (#8267)

* 💄

* prune unused code

* more cleanup

* remove abunch of used code
This commit is contained in:
Anthony Dresser
2019-11-08 11:44:43 -08:00
committed by GitHub
parent 738ca479e4
commit 7f7052ad42
94 changed files with 366 additions and 1158 deletions

View File

@@ -996,7 +996,6 @@
"error-ex": "^1.3.2",
"figures": "^2.0.0",
"find-remove": "1.2.1",
"fs-extra": "^3.0.1",
"kerberos": "^1.1.3",
"request": "^2.88.0",
"request-promise": "^4.2.2",
@@ -1004,14 +1003,16 @@
"stream-meter": "^1.0.4",
"through2": "^3.0.1",
"tough-cookie": "^3.0.1",
"uri-js": "^4.2.2",
"vscode-extension-telemetry": "0.1.0",
"vscode-languageclient": "5.2.1",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/bytes": "^3.0.0",
"@types/kerberos": "^1.1.0",
"@types/request": "^2.48.2",
"@types/request-promise": "^4.1.44",
"@types/stream-meter": "^0.0.22",
"@types/through2": "^2.0.34"
}
}

View File

@@ -85,7 +85,7 @@ export class ApiWrapper {
public openTextDocument(uri: vscode.Uri): Thenable<vscode.TextDocument>;
public openTextDocument(options: { language?: string; content?: string; }): Thenable<vscode.TextDocument>;
public openTextDocument(uriOrOptions): Thenable<vscode.TextDocument> {
public openTextDocument(uriOrOptions: any): Thenable<vscode.TextDocument> {
return vscode.workspace.openTextDocument(uriOrOptions);
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as constants from '../constants';
import * as contracts from '../contracts';

View File

@@ -2,18 +2,18 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as types from './types';
import * as Constants from './constants';
export enum BuiltInCommands {
enum BuiltInCommands {
SetContext = 'setContext',
}
export enum ContextKeys {
enum ContextKeys {
ISCLOUD = 'mssql:iscloud',
EDITIONID = 'mssql:engineedition',
ISCLUSTER = 'mssql:iscluster',
@@ -26,7 +26,7 @@ const isCloudEditions = [
11
];
export function setCommandContext(key: ContextKeys | string, value: any) {
function setCommandContext(key: ContextKeys | string, value: any) {
return vscode.commands.executeCommand(BuiltInCommands.SetContext, key, value);
}

View File

@@ -30,13 +30,13 @@ const resolveBookResources = (extension: vscode.Extension<any>, books: BookContr
return result;
};
export interface BookContribution {
interface BookContribution {
name: string;
path: string;
when?: string;
}
export namespace BookContributions {
namespace BookContributions {
export function merge(a: BookContribution[], b: BookContribution[]): BookContribution[] {
if (!a) {

View File

@@ -2,6 +2,5 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export default require('error-ex')('EscapeException');

View File

@@ -290,7 +290,7 @@ export function parseAclList(aclString: string): AclEntry[] {
* assumes the string has already been checked for validity.
* @param aclString The string representation of the ACL entry
*/
export function parseAclEntry(aclString: string): AclEntry {
function parseAclEntry(aclString: string): AclEntry {
const parts: string[] = aclString.split(':');
let i = 0;
const scope: AclEntryScope = parts.length === 4 && parts[i++] === 'default' ? AclEntryScope.default : AclEntryScope.access;

View File

@@ -15,19 +15,20 @@ import { PermissionStatus, AclEntry, parseAclList, PermissionType, parseAclPermi
import { Mount } from './mount';
import { everyoneName, ownerPostfix, owningGroupPostfix } from '../localizedConstants';
import { FileStatus, parseHdfsFileType } from './fileStatus';
import { Readable, Transform } from 'stream';
const localize = nls.loadMessageBundle();
const ErrorMessageInvalidDataStructure = localize('webhdfs.invalidDataStructure', "Invalid Data Structure");
const emitError = (instance, err) => {
const isErrorEmitted = instance.errorEmitted;
const emitError = (instance: request.Request | Transform, err: any) => {
const isErrorEmitted = (instance as any).errorEmitted;
if (!isErrorEmitted) {
instance.emit('error', err);
instance.emit('finish');
}
instance.errorEmitted = true;
(instance as any).errorEmitted = true;
};
export class WebHDFS {
@@ -41,7 +42,7 @@ export class WebHDFS {
}
let missingProps = ['host', 'port', 'path']
.filter(p => !opts.hasOwnProperty(p) || !opts[p]);
.filter((p: keyof IHdfsOptions) => !opts.hasOwnProperty(p) || !opts[p]);
if (missingProps && missingProps.length > 0) {
throw new Error(localize('webhdfs.missingProperties',
"Unable to create WebHDFS client due to missing options: ${0}", missingProps.join(', ')));
@@ -224,7 +225,7 @@ export class WebHDFS {
);
this.ensureCookie(requestParams);
// Add a wrapper to handle unauthorized requests by adding kerberos auth steps
let handler = (error, response) => {
let handler = (error: any, response: request.Response) => {
if (error && error.statusCode === 401 && this._requestParams.isKerberos) {
this.requestWithKerberosSync(requestParams, callback);
} else {
@@ -234,7 +235,7 @@ export class WebHDFS {
this.doSendRequest(requestParams, handler);
}
private ensureCookie(requestParams: { headers?: {} }) {
private ensureCookie(requestParams: { headers?: { [key: string]: string } }) {
if (this._authCookie && this._authCookie.expiryTime() > Date.now()) {
requestParams.headers = requestParams.headers || {};
requestParams.headers['cookie'] = `${this._authCookie.key}=${this._authCookie.value}`;
@@ -242,7 +243,7 @@ export class WebHDFS {
}
private doSendRequest(requestParams: any, callback: (error: HdfsError, response: any) => void): void {
request(requestParams, (error, response, body) => {
request(requestParams, (error: any, response: request.Response, body: any) => {
if (error || this.isError(response)) {
let hdfsError = this.parseError(response, body, error);
callback(hdfsError, response);
@@ -486,7 +487,7 @@ export class WebHDFS {
// Unknown type - just ignore since we don't currently support the other types
return;
}
e.getAllPermissions().forEach( sp => {
e.getAllPermissions().forEach(sp => {
targetEntry.addPermission(sp.scope, sp.permission);
});
});
@@ -727,7 +728,7 @@ export class WebHDFS {
cb();
}
});
let handleErr = (err) => {
let handleErr = (err: any) => {
replyStream.emit('error', err);
replyStream.end();
};
@@ -735,7 +736,7 @@ export class WebHDFS {
// After redirect, create valid stream to correct location
// and pipe the intermediate stream to it, unblocking the data flow
params.headers['content-type'] = 'application/octet-stream';
let upload = request(params, (err, res, bo) => {
let upload = request(params, (err: any, res: request.Response, bo: any) => {
if (err || this.isError(res)) {
emitError(replyStream, this.parseError(res, bo, err));
replyStream.end();
@@ -760,11 +761,11 @@ export class WebHDFS {
private doCreateWriteStream(params: any): fs.WriteStream {
let canResume: boolean = true;
let stream = undefined;
let req = request(params, (error, response, body) => {
let stream: Readable;
let req = request(params, (error: any, response: request.Response, body: any) => {
// Handle redirect only if there was not an error (e.g. res is defined)
if (response && this.isRedirect(response)) {
let upload = request(Object.assign(params, { url: response.headers.location }), (err, res, bo) => {
let upload = request(Object.assign(params, { url: response.headers.location }), (err: any, res: request.Response, bo: any) => {
if (err || this.isError(res)) {
emitError(req, this.parseError(res, bo, err));
req.end();
@@ -784,7 +785,7 @@ export class WebHDFS {
emitError(req, this.parseError(response, body, error));
}
});
req.on('pipe', (src) => {
req.on('pipe', (src: Readable) => {
// Pause read stream
stream = src;
stream.pause();
@@ -794,7 +795,7 @@ export class WebHDFS {
canResume = false;
stream.on('resume', () => {
if (!canResume) {
stream._readableState.flowing = false;
(stream as any)._readableState.flowing = false; // i guess we are unsafely accessing this
}
});
// Unpipe initial request
@@ -845,7 +846,7 @@ export class WebHDFS {
// Else, must add kerberos token and handle redirects
params.followRedirect = false;
let replyStream = through();
let handleErr = (err) => {
let handleErr = (err: any) => {
replyStream.emit('error', err);
replyStream.end();
};
@@ -960,7 +961,7 @@ export class WebHDFS {
this.unlink(path, recursive, callback);
}
public static createClient(opts, requestParams): WebHDFS {
public static createClient(opts: IHdfsOptions, requestParams: IRequestParams): WebHDFS {
return new WebHDFS(
Object.assign(
{

View File

@@ -181,8 +181,8 @@ async function handleNewNotebookTask(oeContext?: azdata.ObjectExplorerContext, p
async function handleOpenNotebookTask(profile: azdata.IConnectionProfile): Promise<void> {
let notebookFileTypeName = localize('notebookFileType', "Notebooks");
let filter = {};
filter[notebookFileTypeName] = 'ipynb';
let filter: { [key: string]: string[] } = {};
filter[notebookFileTypeName] = ['ipynb'];
let uris = await vscode.window.showOpenDialog({
filters: filter,
canSelectFiles: true,

View File

@@ -15,12 +15,12 @@ import * as utils from '../utils';
import * as constants from '../constants';
import { AppContext } from '../appContext';
export interface ICommandContextParsingOptions {
interface ICommandContextParsingOptions {
editor: boolean;
uri: boolean;
}
export interface ICommandBaseContext {
interface ICommandBaseContext {
command: string;
editor?: vscode.TextEditor;
uri?: vscode.Uri;
@@ -30,7 +30,7 @@ export interface ICommandUnknownContext extends ICommandBaseContext {
type: 'unknown';
}
export interface ICommandUriContext extends ICommandBaseContext {
interface ICommandUriContext extends ICommandBaseContext {
type: 'uri';
}
@@ -44,7 +44,7 @@ export interface ICommandObjectExplorerContext extends ICommandBaseContext {
explorerContext: azdata.ObjectExplorerContext;
}
export type CommandContext = ICommandObjectExplorerContext | ICommandViewContext | ICommandUriContext | ICommandUnknownContext;
type CommandContext = ICommandObjectExplorerContext | ICommandViewContext | ICommandUriContext | ICommandUnknownContext;
function isTextEditor(editor: any): editor is vscode.TextEditor {
if (editor === undefined) { return false; }
@@ -189,4 +189,4 @@ export function registerSearchServerCommand(appContext: AppContext): void {
appContext.apiWrapper.registerCommand('mssql.clearSearchServerResult', () => {
vscode.commands.executeCommand('registeredServers.clearSearchServerResult');
});
}
}

View File

@@ -106,10 +106,11 @@ export interface IFileSource {
exists(path: string): Promise<boolean>;
}
export interface IHttpAuthentication {
interface IHttpAuthentication {
user: string;
pass: string;
}
export interface IHdfsOptions {
host?: string;
port?: number;
@@ -176,7 +177,7 @@ export class FileSourceFactory {
}
}
export class HdfsFileSource implements IFileSource {
class HdfsFileSource implements IFileSource {
private mounts: Map<string, Mount>;
constructor(private client: WebHDFS) {
}
@@ -240,7 +241,7 @@ export class HdfsFileSource implements IFileSource {
public readFile(path: string, maxBytes?: number): Promise<Buffer> {
return new Promise((resolve, reject) => {
let error: HdfsError = undefined;
let remoteFileStream = this.client.createReadStream(path);
let remoteFileStream: fs.ReadStream | meter.StreamMeter = this.client.createReadStream(path);
remoteFileStream.on('error', (err) => {
error = <HdfsError>err;
reject(error);

View File

@@ -71,8 +71,8 @@ export class UploadFilesCommand extends ProgressCommand {
try {
let folderNode = await getNode<FolderNode>(context, this.appContext);
const allFilesFilter = localize('allFiles', "All Files");
let filter = {};
filter[allFilesFilter] = '*';
let filter: { [key: string]: string[] } = {};
filter[allFilesFilter] = ['*'];
if (folderNode) {
let options: vscode.OpenDialogOptions = {
canSelectFiles: true,
@@ -175,7 +175,7 @@ export class MkDirCommand extends ProgressCommand {
}).then(confirmed => <string>confirmed);
}
private async mkDir(fileName, folderNode: FolderNode, cancelToken: vscode.CancellationTokenSource): Promise<void> {
private async mkDir(fileName: string, folderNode: FolderNode, cancelToken: vscode.CancellationTokenSource): Promise<void> {
await folderNode.mkdir(fileName);
}
}

View File

@@ -11,7 +11,7 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import * as Constants from '../constants';
import { IFileSource, IHdfsOptions, IFile, File, FileSourceFactory, FileType } from './fileSources';
import { IFileSource, IFile, File, FileType } from './fileSources';
import { CancelableStream } from './cancelableStream';
import { TreeNode } from './treeNodes';
import * as utils from '../utils';
@@ -28,53 +28,6 @@ export class TreeDataContext {
}
}
export class HdfsProvider implements vscode.TreeDataProvider<TreeNode>, ITreeChangeHandler {
static readonly NoConnectionsMessage = 'No connections added';
static readonly ConnectionsLabel = 'Connections';
private connections: ConnectionNode[];
private _onDidChangeTreeData = new vscode.EventEmitter<TreeNode>();
private context: TreeDataContext;
constructor(extensionContext: vscode.ExtensionContext) {
this.connections = [];
this.context = new TreeDataContext(extensionContext, this);
}
public get onDidChangeTreeData(): vscode.Event<TreeNode> {
return this._onDidChangeTreeData.event;
}
getTreeItem(element: TreeNode): vscode.TreeItem | Thenable<vscode.TreeItem> {
return element.getTreeItem();
}
getChildren(element?: TreeNode): vscode.ProviderResult<TreeNode[]> {
if (element) {
return element.getChildren(false);
} else {
return this.connections.length > 0 ? this.connections : [ErrorNode.create(HdfsProvider.NoConnectionsMessage, element)];
}
}
addConnection(displayName: string, fileSource: IFileSource): void {
if (!this.connections.find(c => c.getDisplayName() === displayName)) {
this.connections.push(new ConnectionNode(this.context, displayName, fileSource));
this._onDidChangeTreeData.fire();
}
}
public async addHdfsConnection(options: IHdfsOptions): Promise<void> {
let displayName = `${options.user}@${options.host}:${options.port}`;
let fileSource = await FileSourceFactory.instance.createHdfsFileSource(options);
this.addConnection(displayName, fileSource);
}
notifyNodeChanged(node: TreeNode): void {
this._onDidChangeTreeData.fire(node);
}
}
export abstract class HdfsFileSourceNode extends TreeNode {
constructor(protected context: TreeDataContext, protected _path: string, public readonly fileSource: IFileSource, protected mountStatus?: MountStatus) {
super();
@@ -362,7 +315,7 @@ export class FileNode extends HdfsFileSourceNode implements IFileNode {
}
}
export class ErrorNode extends TreeNode {
class ErrorNode extends TreeNode {
static messageNum: number = 0;
private _nodePathValue: string;

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
@@ -72,7 +70,7 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd
private async doExpandNode(nodeInfo: azdata.ExpandNodeInfo, isRefresh: boolean = false): Promise<boolean> {
let session = this.sessionMap.get(nodeInfo.sessionId);
let response = {
let response: azdata.ObjectExplorerExpandInfo = {
sessionId: nodeInfo.sessionId,
nodePath: nodeInfo.nodePath,
errorMessage: undefined,
@@ -235,7 +233,7 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd
}
}
export class SqlClusterSession {
class SqlClusterSession {
private _rootNode: SqlClusterRootNode;
constructor(

View File

@@ -4,13 +4,13 @@
import { window } from 'vscode';
import PromptFactory from './factory';
import EscapeException from '../escapeException';
import { IQuestion, IPrompter, IPromptCallback } from './question';
import { IQuestion, IPrompter } from './question';
// Supports simple pattern for prompting for user input and acting on this
export default class CodeAdapter implements IPrompter {
// TODO define question interface
private fixQuestion(question: any): any {
private fixQuestion(question: IQuestion): any {
if (question.type === 'checkbox' && Array.isArray(question.choices)) {
// For some reason when there's a choice of checkboxes, they aren't formatted properly
// Not sure where the issue is
@@ -46,7 +46,7 @@ export default class CodeAdapter implements IPrompter {
return PromptFactory.createPrompt(question, ignoreFocusOut);
}).then(prompt => {
if (!question.shouldPrompt || question.shouldPrompt(answers) === true) {
return prompt.render().then(result => {
return prompt.render().then((result: T) => {
answers[question.name] = result;
if (question.onAnswered) {
@@ -67,14 +67,4 @@ export default class CodeAdapter implements IPrompter {
window.showErrorMessage(err.message);
});
}
// Helper to make it possible to prompt using callback pattern. Generally Promise is a preferred flow
public promptCallback(questions: IQuestion[], callback: IPromptCallback): void {
// Collapse multiple questions into a set of prompt steps
this.prompt(questions).then(answers => {
if (callback) {
callback(answers);
}
});
}
}

View File

@@ -1,52 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window } from 'vscode';
import Prompt from './prompt';
import EscapeException from '../escapeException';
const figures = require('figures');
export default class CheckboxPrompt extends Prompt {
constructor(question: any, ignoreFocusOut?: boolean) {
super(question, ignoreFocusOut);
}
public render(): any {
let choices = this._question.choices.reduce((result, choice) => {
let choiceName = choice.name || choice;
result[`${choice.checked === true ? figures.radioOn : figures.radioOff} ${choiceName}`] = choice;
return result;
}, {});
let options = this.defaultQuickPickOptions;
options.placeHolder = this._question.message;
let quickPickOptions = Object.keys(choices);
quickPickOptions.push(figures.tick);
return window.showQuickPick(quickPickOptions, options)
.then(result => {
if (result === undefined) {
throw new EscapeException();
}
if (result !== figures.tick) {
choices[result].checked = !choices[result].checked;
return this.render();
}
return this._question.choices.reduce((result2, choice) => {
if (choice.checked === true) {
result2.push(choice.value);
}
return result2;
}, []);
});
}
}

View File

@@ -1,5 +1,3 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE

View File

@@ -1,78 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import vscode = require('vscode');
import Prompt from './prompt';
import EscapeException from '../escapeException';
import { INameValueChoice } from './question';
const figures = require('figures');
export default class ExpandPrompt extends Prompt {
constructor(question: any, ignoreFocusOut?: boolean) {
super(question, ignoreFocusOut);
}
public render(): any {
// label indicates this is a quickpick item. Otherwise it's a name-value pair
if (this._question.choices[0].label) {
return this.renderQuickPick(this._question.choices);
} else {
return this.renderNameValueChoice(this._question.choices);
}
}
private renderQuickPick(choices: vscode.QuickPickItem[]): any {
let options = this.defaultQuickPickOptions;
options.placeHolder = this._question.message;
return vscode.window.showQuickPick(choices, options)
.then(result => {
if (result === undefined) {
throw new EscapeException();
}
return this.validateAndReturn(result || false);
});
}
private renderNameValueChoice(choices: INameValueChoice[]): any {
const choiceMap = this._question.choices.reduce((result, choice) => {
result[choice.name] = choice.value;
return result;
}, {});
let options = this.defaultQuickPickOptions;
options.placeHolder = this._question.message;
return vscode.window.showQuickPick(Object.keys(choiceMap), options)
.then(result => {
if (result === undefined) {
throw new EscapeException();
}
// Note: cannot be used with 0 or false responses
let returnVal = choiceMap[result] || false;
return this.validateAndReturn(returnVal);
});
}
private validateAndReturn(value: any): any {
if (!this.validate(value)) {
return this.render();
}
return value;
}
private validate(value: any): boolean {
const validationError = this._question.validate ? this._question.validate(value || '') : undefined;
if (validationError) {
this._question.message = `${figures.warning} ${validationError}`;
return false;
}
return true;
}
}

View File

@@ -1,33 +1,22 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import Prompt from './prompt';
import InputPrompt from './input';
import PasswordPrompt from './password';
import ListPrompt from './list';
import ConfirmPrompt from './confirm';
import CheckboxPrompt from './checkbox';
import ExpandPrompt from './expand';
import { IQuestion } from './question';
export default class PromptFactory {
public static createPrompt(question: any, ignoreFocusOut?: boolean): Prompt {
switch (question.type || 'input') {
case 'string':
public static createPrompt(question: IQuestion, ignoreFocusOut?: boolean): Prompt {
switch (question.type) {
case 'input':
return new InputPrompt(question, ignoreFocusOut);
case 'password':
return new PasswordPrompt(question, ignoreFocusOut);
case 'list':
return new ListPrompt(question, ignoreFocusOut);
case 'confirm':
return new ConfirmPrompt(question, ignoreFocusOut);
case 'checkbox':
return new CheckboxPrompt(question, ignoreFocusOut);
case 'expand':
return new ExpandPrompt(question, ignoreFocusOut);
default:
throw new Error(`Could not find a prompt for question type ${question.type}`);
}

View File

@@ -1,5 +1,3 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE

View File

@@ -1,33 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window } from 'vscode';
import Prompt from './prompt';
import EscapeException from '../escapeException';
export default class ListPrompt extends Prompt {
constructor(question: any, ignoreFocusOut?: boolean) {
super(question, ignoreFocusOut);
}
public render(): any {
const choices = this._question.choices.reduce((result, choice) => {
result[choice.name] = choice.value;
return result;
}, {});
let options = this.defaultQuickPickOptions;
options.placeHolder = this._question.message;
return window.showQuickPick(Object.keys(choices), options)
.then(result => {
if (result === undefined) {
throw new EscapeException();
}
return choices[result];
});
}
}

View File

@@ -1,5 +1,3 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE

View File

@@ -1,70 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import {window, StatusBarItem, StatusBarAlignment} from 'vscode';
export default class ProgressIndicator {
private _statusBarItem: StatusBarItem;
constructor() {
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
}
private _tasks: string[] = [];
public beginTask(task: string): void {
this._tasks.push(task);
this.displayProgressIndicator();
}
public endTask(task: string): void {
if (this._tasks.length > 0) {
this._tasks.pop();
}
this.setMessage();
}
private setMessage(): void {
if (this._tasks.length === 0) {
this._statusBarItem.text = '';
this.hideProgressIndicator();
return;
}
this._statusBarItem.text = this._tasks[this._tasks.length - 1];
this._statusBarItem.show();
}
private _interval: any;
private displayProgressIndicator(): void {
this.setMessage();
this.hideProgressIndicator();
this._interval = setInterval(() => this.onDisplayProgressIndicator(), 100);
}
private hideProgressIndicator(): void {
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
this.ProgressCounter = 0;
}
private ProgressText = ['|', '/', '-', '\\', '|', '/', '-', '\\'];
private ProgressCounter = 0;
private onDisplayProgressIndicator(): void {
if (this._tasks.length === 0) {
return;
}
let txt = this.ProgressText[this.ProgressCounter];
this._statusBarItem.text = this._tasks[this._tasks.length - 1] + ' ' + txt;
this.ProgressCounter++;
if (this.ProgressCounter >= this.ProgressText.length - 1) {
this.ProgressCounter = 0;
}
}
}

View File

@@ -1,16 +1,15 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { InputBoxOptions, QuickPickOptions } from 'vscode';
import { IQuestion } from './question';
abstract class Prompt {
protected _question: any;
protected _question: IQuestion;
protected _ignoreFocusOut?: boolean;
constructor(question: any, ignoreFocusOut?: boolean) {
constructor(question: IQuestion, ignoreFocusOut?: boolean) {
this._question = question;
this._ignoreFocusOut = ignoreFocusOut ? ignoreFocusOut : false;
}

View File

@@ -3,15 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import vscode = require('vscode');
import * as vscode from 'vscode';
export class QuestionTypes {
public static get input(): string { return 'input'; }
public static get password(): string { return 'password'; }
public static get list(): string { return 'list'; }
public static get confirm(): string { return 'confirm'; }
public static get checkbox(): string { return 'checkbox'; }
public static get expand(): string { return 'expand'; }
}
// Question interface to clarify how to use the prompt feature
@@ -40,19 +37,11 @@ export interface IQuestion {
}
// Pair used to display simple choices to the user
export interface INameValueChoice {
interface INameValueChoice {
name: string;
value: any;
}
// Generic object that can be used to define a set of questions and handle the result
export interface IQuestionHandler {
// Set of questions to be answered
questions: IQuestion[];
// Optional callback, since questions may handle themselves
callback?: IPromptCallback;
}
export interface IPrompter {
promptSingle<T>(question: IQuestion, ignoreFocusOut?: boolean): Promise<T>;
/**
@@ -61,10 +50,5 @@ export interface IPrompter {
* @returns Map of question IDs to results, or undefined if
* the user canceled the question session
*/
prompt<T>(questions: IQuestion[], ignoreFocusOut?: boolean): Promise<{ [questionId: string]: any }>;
promptCallback(questions: IQuestion[], callback: IPromptCallback): void;
}
export interface IPromptCallback {
(answers: { [id: string]: any }): void;
prompt(questions: IQuestion[], ignoreFocusOut?: boolean): Promise<{ [questionId: string]: any }>;
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export const serviceName = 'AzureResourceProvider';
export const providerId = 'azureresourceProvider';

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { RequestType } from 'vscode-languageclient';
import * as azdata from 'azdata';
@@ -25,7 +24,7 @@ export interface CreateFirewallRuleParams {
securityTokenMappings: {};
}
export interface CreateFirewallRuleResponse {
interface CreateFirewallRuleResponse {
result: boolean;
errorMessage: string;
}
@@ -36,7 +35,7 @@ export interface HandleFirewallRuleParams {
connectionTypeId: string;
}
export interface HandleFirewallRuleResponse {
interface HandleFirewallRuleResponse {
result: boolean;
ipAddress: string;
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { IConfig, ServerProvider } from 'service-downloader';

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as nls from 'vscode-nls';
import * as vscode from 'vscode';

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';

View File

@@ -38,7 +38,7 @@ export class SparkJobSubmissionModel {
private readonly _sqlClusterConnection: SqlClusterConnection,
private readonly _dialog: azdata.window.Dialog,
private readonly _appContext: AppContext,
requestService?: (args: any) => any) {
requestService?: typeof import('request-promise')) {
if (!this._sqlClusterConnection || !this._dialog || !this._appContext) {
throw new Error(localize('sparkJobSubmission.SparkJobSubmissionModelInitializeError',

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as os from 'os';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
@@ -12,12 +10,13 @@ import * as constants from '../../../constants';
import { SqlClusterConnection } from '../../../objectExplorerNodeProvider/connection';
import * as utils from '../../../utils';
import * as auth from '../../../util/auth';
import { Options } from 'request-promise';
export class SparkJobSubmissionService {
private _requestPromise: (args: any) => any;
private _requestPromise: typeof import('request-promise');
constructor(
requestService?: (args: any) => any) {
requestService?: typeof import('request-promise')) {
if (requestService) {
// this is to fake the request service for test.
this._requestPromise = requestService;
@@ -33,7 +32,7 @@ export class SparkJobSubmissionService {
// Get correct authentication headers
let headers = await this.getAuthenticationHeaders(submissionArgs);
let options = {
let options: Options = {
uri: livyUrl,
method: 'POST',
json: true,

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { AppContext } from '../appContext';

View File

@@ -1,217 +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 childProcess from 'child_process';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as which from 'which';
import * as constants from '../constants';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export function getDropdownValue(dropdownValue: string | azdata.CategoryValue): string {
if (typeof (dropdownValue) === 'string') {
return <string>dropdownValue;
} else {
return dropdownValue ? (<azdata.CategoryValue>dropdownValue).name : undefined;
}
}
export function getServerAddressFromName(connection: azdata.ConnectionInfo | string): string {
// Strip TDS port number from the server URI
if ((<azdata.ConnectionInfo>connection).options && (<azdata.ConnectionInfo>connection).options[constants.hostPropName]) {
return (<azdata.ConnectionInfo>connection).options[constants.hostPropName].split(',')[0].split(':')[0];
} else if ((<azdata.ConnectionInfo>connection).options && (<azdata.ConnectionInfo>connection).options['server']) {
return (<azdata.ConnectionInfo>connection).options['server'].split(',')[0].split(':')[0];
} else {
return (<string>connection).split(',')[0].split(':')[0];
}
}
export function getKnoxUrl(host: string, port: string): string {
return `https://${host}:${port}/gateway`;
}
export function getLivyUrl(serverName: string, port: string): string {
return this.getKnoxUrl(serverName, port) + '/default/livy/v1/';
}
export function getTemplatePath(extensionPath: string, templateName: string): string {
return path.join(extensionPath, 'resources', templateName);
}
export function shellWhichResolving(cmd: string): Promise<string> {
return new Promise<string>(resolve => {
which(cmd, async (err, foundPath) => {
if (err) {
resolve(undefined);
} else {
// NOTE: Using realpath b/c some system installs are symlinked from */bin
resolve(await fs.promises.realpath(foundPath));
}
});
});
}
export async function mkDir(dirPath: string, outputChannel?: vscode.OutputChannel): Promise<void> {
if (!await fs.exists(dirPath)) {
if (outputChannel) {
outputChannel.appendLine(localize('mkdirOutputMsg', "... Creating {0}", dirPath));
}
await fs.ensureDir(dirPath);
}
}
export function getErrorMessage(error: Error | string): string {
return (error instanceof Error) ? error.message : error;
}
// COMMAND EXECUTION HELPERS ///////////////////////////////////////////////
export function executeBufferedCommand(cmd: string, options: childProcess.ExecOptions, outputChannel?: vscode.OutputChannel): Thenable<string> {
return new Promise<string>((resolve, reject) => {
if (outputChannel) {
outputChannel.appendLine(` > ${cmd}`);
}
let child = childProcess.exec(cmd, options, (err, stdout) => {
if (err) {
reject(err);
} else {
resolve(stdout);
}
});
// Add listeners to print stdout and stderr if an output channel was provided
if (outputChannel) {
child.stdout.on('data', data => { outputDataChunk(data, outputChannel, ' stdout: '); });
child.stderr.on('data', data => { outputDataChunk(data, outputChannel, ' stderr: '); });
}
});
}
export function executeExitCodeCommand(cmd: string, outputChannel?: vscode.OutputChannel): Thenable<number> {
return new Promise<number>((resolve, reject) => {
if (outputChannel) {
outputChannel.appendLine(` > ${cmd}`);
}
let child = childProcess.spawn(cmd, [], { shell: true, detached: false });
// Add listeners for the process to exit
child.on('error', reject);
child.on('exit', (code: number) => { resolve(code); });
// Add listeners to print stdout and stderr if an output channel was provided
if (outputChannel) {
child.stdout.on('data', data => { outputDataChunk(data, outputChannel, ' stdout: '); });
child.stderr.on('data', data => { outputDataChunk(data, outputChannel, ' stderr: '); });
}
});
}
export function executeStreamedCommand(cmd: string, outputChannel?: vscode.OutputChannel): Thenable<void> {
return new Promise<void>((resolve, reject) => {
// Start the command
if (outputChannel) {
outputChannel.appendLine(` > ${cmd}`);
}
let child = childProcess.spawn(cmd, [], { shell: true, detached: false });
// Add listeners to resolve/reject the promise on exit
child.on('error', reject);
child.on('exit', (code: number) => {
if (code === 0) {
resolve();
} else {
reject(localize('executeCommandProcessExited', "Process exited with code {0}", code));
}
});
// Add listeners to print stdout and stderr if an output channel was provided
if (outputChannel) {
child.stdout.on('data', data => { outputDataChunk(data, outputChannel, ' stdout: '); });
child.stderr.on('data', data => { outputDataChunk(data, outputChannel, ' stderr: '); });
}
});
}
export function isObjectExplorerContext(object: any): object is azdata.ObjectExplorerContext {
return 'connectionProfile' in object && 'isConnectionNode' in object;
}
export function getUserHome(): string {
return process.env.HOME || process.env.USERPROFILE;
}
export enum Platform {
Mac,
Linux,
Windows,
Others
}
export function getOSPlatform(): Platform {
switch (process.platform) {
case 'win32':
return Platform.Windows;
case 'darwin':
return Platform.Mac;
case 'linux':
return Platform.Linux;
default:
return Platform.Others;
}
}
export function getOSPlatformId(): string {
let platformId = undefined;
switch (process.platform) {
case 'win32':
platformId = 'win-x64';
break;
case 'darwin':
platformId = 'osx';
break;
default:
platformId = 'linux-x64';
break;
}
return platformId;
}
// PRIVATE HELPERS /////////////////////////////////////////////////////////
function outputDataChunk(data: string | Buffer, outputChannel: vscode.OutputChannel, header: string): void {
data.toString().split(/\r?\n/)
.forEach(line => {
outputChannel.appendLine(header + line);
});
}
export function clone<T>(obj: T): T {
if (!obj || typeof obj !== 'object') {
return obj;
}
if (obj instanceof RegExp) {
// See https://github.com/Microsoft/TypeScript/issues/10990
return obj as any;
}
const result = (Array.isArray(obj)) ? <any>[] : <any>{};
Object.keys(obj).forEach(key => {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = clone(obj[key]);
} else {
result[key] = obj[key];
}
});
return result;
}
export function isValidNumber(maybeNumber: any) {
return maybeNumber !== undefined
&& maybeNumber !== null
&& maybeNumber !== ''
&& !isNaN(Number(maybeNumber.toString()));
}

View File

@@ -26,7 +26,7 @@ export interface ITelemetryEventMeasures {
/**
* Filters error paths to only include source files. Exported to support testing
*/
export function FilterErrorPath(line: string): string {
function FilterErrorPath(line: string): string {
if (line) {
let values: string[] = line.split('/out/');
if (values.length <= 1) {

View File

@@ -0,0 +1,19 @@
declare module 'buffer-stream-reader' {
import * as fs from 'fs';
class BufferStreamReader {
constructor(stream: string | Buffer);
pipe(pipe: fs.WriteStream): void
}
namespace BufferStreamReader {
interface FindRemoveOptions {
age?: {
seconds?: number;
};
limit?: number;
}
}
export = BufferStreamReader;
}

View File

@@ -0,0 +1,17 @@
declare module 'find-remove' {
namespace findRemove {
interface FindRemoveApi {
(path: string, options: FindRemoveOptions): JSON;
}
interface FindRemoveOptions {
age?: {
seconds?: number;
};
limit?: number;
}
}
const findRemove: findRemove.FindRemoveApi;
export = findRemove;
}

View File

@@ -5,7 +5,7 @@
import * as vscode from 'vscode';
export function disposeAll(disposables: vscode.Disposable[]) {
function disposeAll(disposables: vscode.Disposable[]) {
while (disposables.length) {
const item = disposables.pop();
if (item) {
@@ -39,4 +39,4 @@ export abstract class Disposable {
protected get isDisposed() {
return this._isDisposed;
}
}
}

View File

@@ -107,7 +107,7 @@ export function getCommonLaunchArgsAndCleanupOldLogFiles(logPath: string, fileNa
return launchArgs;
}
export function ensure(target: object, key: string): any {
export function ensure(target: { [key: string]: any }, key: string): any {
if (target[key] === void 0) {
target[key] = {} as any;
}

View File

@@ -3,8 +3,7 @@
"compilerOptions": {
"outDir": "./out",
"strict": false,
"noUnusedParameters": false,
"noImplicitAny": false
"noUnusedParameters": false
},
"include": [
"src/**/*"

View File

@@ -2,6 +2,16 @@
# yarn lockfile v1
"@types/bluebird@*":
version "3.5.28"
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.28.tgz#04c1a520ff076649236bc8ca21198542ce2bdb09"
integrity sha512-0Vk/kqkukxPKSzP9c8WJgisgGDx5oZDbsLLWIP5t70yThO/YleE+GEm2S1GlRALTaack3O7U5OS5qEm7q2kciA==
"@types/bytes@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.0.0.tgz#549eeacd0a8fecfaa459334583a4edcee738e6db"
integrity sha512-ZF43+CIIlzngQe8/Zo7L1kpY9W8O6rO006VDz3c5iM21ddtXWxCEyOXyft+q4pVF2tGqvrVuVrEDH1+gJEi1fQ==
"@types/caseless@*":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
@@ -17,6 +27,24 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44"
integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==
"@types/request-promise@^4.1.44":
version "4.1.44"
resolved "https://registry.yarnpkg.com/@types/request-promise/-/request-promise-4.1.44.tgz#05b59cd18445832fae16b68d5bb3d4621b549485"
integrity sha512-RId7eFsUKxfal1LirDDIcOp9u3MM3NXFDBcC3sqIMcmu7f4U6DsCEMD8RbLZtnPrQlN5Jc79di/WPsIEDO4keg==
dependencies:
"@types/bluebird" "*"
"@types/request" "*"
"@types/request@*":
version "2.48.3"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.3.tgz#970b8ed2317568c390361d29c555a95e74bd6135"
integrity sha512-3Wo2jNYwqgXcIz/rrq18AdOZUQB8cQ34CXZo+LUwPJNpvRAL86+Kc2wwI8mqpz9Cr1V+enIox5v+WZhy/p3h8w==
dependencies:
"@types/caseless" "*"
"@types/node" "*"
"@types/tough-cookie" "*"
form-data "^2.5.0"
"@types/request@^2.48.2":
version "2.48.2"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.2.tgz#936374cbe1179d7ed529fc02543deb4597450fed"
@@ -27,6 +55,13 @@
"@types/tough-cookie" "*"
form-data "^2.5.0"
"@types/stream-meter@^0.0.22":
version "0.0.22"
resolved "https://registry.yarnpkg.com/@types/stream-meter/-/stream-meter-0.0.22.tgz#6602f644ea0f5468cae13931ee6611a3a03fbab1"
integrity sha512-gqqudd3q69aEmixGIL1p2qN1AySZ+UJ2j6y70ZXZBg8/SmzTM1MvkOKvmuelKNIpPS8bKml6Gw03pfbnI8YpwQ==
dependencies:
"@types/node" "*"
"@types/through2@^2.0.34":
version "2.0.34"
resolved "https://registry.yarnpkg.com/@types/through2/-/through2-2.0.34.tgz#9c2a259a238dace2a05a2f8e94b786961bc27ac4"
@@ -534,15 +569,6 @@ fs-constants@^1.0.0:
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291"
integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=
dependencies:
graceful-fs "^4.1.2"
jsonfile "^3.0.0"
universalify "^0.1.0"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -594,7 +620,7 @@ glob@^7.0.5:
once "^1.3.0"
path-is-absolute "^1.0.0"
graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
graceful-fs@^4.1.10:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
@@ -742,13 +768,6 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsonfile@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=
optionalDependencies:
graceful-fs "^4.1.6"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -1320,11 +1339,6 @@ unbzip2-stream@^1.0.9:
buffer "^5.2.1"
through "^2.3.8"
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"