diff --git a/.eslintrc.js b/.eslintrc.js index 1cf2945d..ad40c4d0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { ignorePatterns: ["**/*.d.ts", "**/*.js"], parser: "@typescript-eslint/parser", extends: ["plugin:@typescript-eslint/recommended"], - plugins: ["header", "license-header"], + plugins: ["header", "license-header", "unused-imports"], parserOptions: { ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features sourceType: "module", // Allows for the use of imports @@ -12,7 +12,20 @@ module.exports = { "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "off", "license-header/header": ["error", "./resources/license-header.js"], + "@typescript-eslint/no-unused-vars": "off", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": [ + "warn", + { + vars: "all", + varsIgnorePattern: "^_", + args: "after-used", + argsIgnorePattern: "^_", + }, + ], + // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs // e.g. "@typescript-eslint/explicit-function-return-type": "off", }, diff --git a/package-lock.json b/package-lock.json index 24069fb6..04ed628b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,6 +64,7 @@ "eslint": "^8.56.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-license-header": "^0.6.0", + "eslint-plugin-unused-imports": "^3.2.0", "glob": "^8.1.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-instrument": "^3.3.0", @@ -2260,6 +2261,36 @@ "requireindex": "^1.2.0" } }, + "node_modules/eslint-plugin-unused-imports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz", + "integrity": "sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==", + "dev": true, + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "6 - 7", + "eslint": "8" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -6970,6 +7001,21 @@ "requireindex": "^1.2.0" } }, + "eslint-plugin-unused-imports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz", + "integrity": "sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==", + "dev": true, + "requires": { + "eslint-rule-composer": "^0.3.0" + } + }, + "eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true + }, "eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", diff --git a/package.json b/package.json index a066a385..9bcc67d2 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "kdb", "description": "IDE support for kdb product suite", "publisher": "KX", - "version": "1.4.0", + "version": "1.5.0", "engines": { "vscode": "^1.75.0" }, @@ -773,7 +773,8 @@ "coverage": "tsc -p ./test && node ./out/test/runTest.js --coverage", "package": "npx vsce package", "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"", - "publish": "npx vsce publish" + "publish": "npx vsce publish", + "lint": "eslint 'src/**' --fix" }, "prettier": { "printWidth": 80, @@ -804,6 +805,7 @@ "eslint": "^8.56.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-license-header": "^0.6.0", + "eslint-plugin-unused-imports": "^3.2.0", "glob": "^8.1.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-instrument": "^3.3.0", diff --git a/src/extension.ts b/src/extension.ts index 0a515c74..d37be882 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,18 +14,18 @@ import { env } from "node:process"; import path from "path"; import { - commands, ConfigurationTarget, EventEmitter, ExtensionContext, - extensions, - languages, Range, TextDocumentContentProvider, Uri, + WorkspaceEdit, + commands, + extensions, + languages, window, workspace, - WorkspaceEdit, } from "vscode"; import { LanguageClient, @@ -56,7 +56,6 @@ import { ExecutionTypes } from "./models/execution"; import { InsightDetails, Insights } from "./models/insights"; import { QueryResult } from "./models/queryResult"; import { Server, ServerDetails } from "./models/server"; -import { KdbDataSourceProvider } from "./services/dataSourceTreeProvider"; import { InsightsNode, KdbNode, @@ -79,13 +78,13 @@ import AuthSettings from "./utils/secretStorage"; import { Telemetry } from "./utils/telemetryClient"; import { DataSourceEditorProvider } from "./services/dataSourceEditorProvider"; import { - addWorkspaceFile, FileTreeItem, WorkspaceTreeProvider, + addWorkspaceFile, } from "./services/workspaceTreeProvider"; import { - checkOldDatasourceFiles, ConnectionLensProvider, + checkOldDatasourceFiles, connectWorkspaceCommands, importOldDSFiles, pickConnection, @@ -108,7 +107,6 @@ export async function activate(context: ExtensionContext) { const insights: Insights | undefined = getInsights(); ext.serverProvider = new KdbTreeProvider(servers!, insights!); - ext.dataSourceProvider = new KdbDataSourceProvider(); ext.queryHistoryProvider = new QueryHistoryProvider(); ext.resultsViewProvider = new KdbResultsViewProvider( ext.context.extensionUri, @@ -480,9 +478,6 @@ export async function activate(context: ExtensionContext) { export async function deactivate(): Promise { await Telemetry.dispose(); - if (ext.dataSourceProvider) { - ext.dataSourceProvider.dispose(); - } // cleanup of local q instance processes Object.keys(ext.localProcessObjects).forEach((index) => { diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index ca51b504..d295b420 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -24,7 +24,6 @@ import { LocalProcess } from "./models/localProcess"; import { MetaObjectPayload } from "./models/meta"; import { QueryHistory } from "./models/queryHistory"; import { ServerObject } from "./models/serverObject"; -import { KdbDataSourceProvider } from "./services/dataSourceTreeProvider"; import { InsightsNode, KdbNode, @@ -46,7 +45,6 @@ export namespace ext { export let outputChannel: OutputChannel; export let consolePanel: OutputChannel; export let serverProvider: KdbTreeProvider; - export let dataSourceProvider: KdbDataSourceProvider; export let queryHistoryProvider: QueryHistoryProvider; export let resultsViewProvider: KdbResultsViewProvider; export let scratchpadTreeProvider: WorkspaceTreeProvider; diff --git a/src/ipc/I64.ts b/src/ipc/I64.ts index f33bb221..da882f45 100644 --- a/src/ipc/I64.ts +++ b/src/ipc/I64.ts @@ -22,7 +22,7 @@ export default abstract class I64 extends Vector { length: number, offset: number, qtype: number, - dataView: DataView + dataView: DataView, ) { super(length, offset, qtype, dataView, 8); } @@ -30,14 +30,14 @@ export default abstract class I64 extends Vector { calcRange(): bigint[] { let xMax = this.getScalar(0); let xMin = xMax; - // @ts-ignore TS2304 + // TS2304 for (let i = 1; i < this.length; i++) { const x = this.getScalar(i); - // @ts-ignore TS2304 + // TS2304 if (xMax === I64.nullValue || (x > xMax && x !== I64.nullValue)) { xMax = x; } - // @ts-ignore TS2304 + // TS2304 if (xMin === I64.nullValue || (x < xMin && x !== I64.nullValue)) { xMin = x; } @@ -50,7 +50,7 @@ export default abstract class I64 extends Vector { */ public deserializeScalar( scalar: bigint, - deserialize: (scalar: bigint) => DType + deserialize: (scalar: bigint) => DType, ): DType | number | null { if (scalar === I64.nullValue) { return null; @@ -68,7 +68,7 @@ export default abstract class I64 extends Vector { */ public deserializeScalarAt( index: number, - deserialize: (scalar: bigint) => DType + deserialize: (scalar: bigint) => DType, ): DType | number | null { const s = this.getScalar(index); return this.deserializeScalar(s, deserialize); diff --git a/src/ipc/vector.ts b/src/ipc/vector.ts index 36ba761f..506d9b82 100644 --- a/src/ipc/vector.ts +++ b/src/ipc/vector.ts @@ -28,7 +28,7 @@ export default abstract class Vector extends TypeBase { offset: number, qtype: number, dataView: DataView, - size: number + size: number, ) { super(length, offset, qtype); this.dataView = dataView; @@ -54,9 +54,9 @@ export default abstract class Vector extends TypeBase { new Uint8Array( this.dataView.buffer, this.offset, - arg.length * this.size + arg.length * this.size, ).set( - new Uint8Array(arg.dataView.buffer, arg.offset, arg.length * this.size) + new Uint8Array(arg.dataView.buffer, arg.offset, arg.length * this.size), ); } @@ -79,12 +79,12 @@ export default abstract class Vector extends TypeBase { if (this.size !== 8 || [9, 15].indexOf(this.qtype) !== -1) { const compareFn = (x: number, y: number): number => x - (this.hash(y) as number); - // @ts-ignore + // @ts-expect-error return Tools.binarySearch2(Number(value), this.index, compareFn); } else { const compareFn = (x: bigint, y: number): number => Number(x - (this.hash(y) as bigint)); - // @ts-ignore + // @ts-expect-error return Tools.binarySearch2(BigInt(value), this.index, compareFn); } } @@ -92,7 +92,7 @@ export default abstract class Vector extends TypeBase { public mergeKeyedPrimary( arg: Vector, maxRows: number, - insertIndices: Array + insertIndices: Array, ): number { this.resetRangeCache(); this.index = this.index ? this.index : this.generateIndex(); @@ -121,13 +121,13 @@ export default abstract class Vector extends TypeBase { new Uint8Array( this.dataView.buffer, this.offset + targetIndex * this.size, - this.size + this.size, ).set( new Uint8Array( arg.dataView.buffer, arg.offset + i * this.size, - this.size - ) + this.size, + ), ); insertIndices.push(targetIndex); } else { @@ -142,7 +142,7 @@ export default abstract class Vector extends TypeBase { arg: Vector, indices: Array, indexOffset: number, - maxRows: number + maxRows: number, ): void { this.resetRangeCache(); for (let i = 0; i < indices.length; i++) { @@ -159,13 +159,13 @@ export default abstract class Vector extends TypeBase { new Uint8Array( this.dataView.buffer, this.offset + targetIndex * this.size, - this.size + this.size, ).set( new Uint8Array( arg.dataView.buffer, arg.offset + i * this.size, - this.size - ) + this.size, + ), ); } @@ -176,7 +176,11 @@ export default abstract class Vector extends TypeBase { this.bufferLength = extLength || this.bufferLength; const buffer = new ArrayBuffer(this.bufferLength * this.size); new Uint8Array(buffer, 0, this.length * this.size).set( - new Uint8Array(this.dataView.buffer, this.offset, this.length * this.size) + new Uint8Array( + this.dataView.buffer, + this.offset, + this.length * this.size, + ), ); this.dataView = new DataView(buffer); @@ -216,14 +220,14 @@ export default abstract class Vector extends TypeBase { new TA( this.dataView.buffer, this.indexOffset * this.size, - this.length - this.indexOffset - ) + this.length - this.indexOffset, + ), ); typedArray.set( // @ts-ignore new TA(this.dataView.buffer, 0, this.indexOffset), - this.length - this.indexOffset + this.length - this.indexOffset, ); return typedArray; @@ -252,7 +256,7 @@ export default abstract class Vector extends TypeBase { index.sort((a, b) => (this.hash(a) as number) - (this.hash(b) as number)); } else { index.sort((a, b) => - Number((this.hash(a) as bigint) - (this.hash(b) as bigint)) + Number((this.hash(a) as bigint) - (this.hash(b) as bigint)), ); } diff --git a/src/models/connection.ts b/src/models/connection.ts deleted file mode 100644 index 0820f77b..00000000 --- a/src/models/connection.ts +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 1998-2023 Kx Systems Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -// will be removed before the next release -// import * as nodeq from "node-q"; -// import { commands, window } from "vscode"; -// import { ext } from "../extensionVariables"; -// import { delay } from "../utils/core"; -// import { convertStringToArray, handleQueryResults } from "../utils/execution"; -// import { queryWrapper } from "../utils/queryUtils"; -// import { QueryResult, QueryResultType } from "./queryResult"; - -// export class Connection { -// private options: nodeq.ConnectionParameters; -// private connection?: nodeq.Connection; -// public connected: boolean; -// private isError: boolean = false; -// private result?: string; - -// constructor(connectionString: string, creds?: string[], tls?: boolean) { -// const params = connectionString.split(":"); -// if (!params) { -// throw new Error("Missing or invalid connection string"); -// } - -// const options: nodeq.ConnectionParameters = { -// nanos2date: false, -// socketNoDelay: true, -// }; - -// if (tls != undefined) { -// options.useTLS = tls; -// } else { -// options.useTLS = false; -// } - -// if (params.length > 0) { -// options.host = params[0]; -// } -// if (params.length > 1) { -// options.port = +params[1]; -// } - -// if (creds != undefined) { -// options.user = creds[0]; -// options.password = creds[1]; -// } - -// this.options = options; -// this.connected = false; -// } - -// public disconnect(): void { -// if (this.connected) { -// this.connection?.close(); -// this.connected = false; -// } -// } - -// public async execute(command: string): Promise { -// let result; -// let error; -// // try 5 times, then fail -// let retryCount = 0; -// while (this.connection === undefined) { -// if (retryCount > ext.maxRetryCount) { -// return "timeout"; -// } -// await delay(500); -// retryCount++; -// } - -// this.connection.k(command, function (err: Error, res: string) { -// if (err) { -// error = err; -// result = ""; -// return; -// } -// result = res; -// }); - -// // wait for result (lack of await using callbacks) -// while (result === undefined || result === null) { -// await delay(500); -// } - -// if (error) { -// throw error; -// } - -// return result; -// } - -// public async executeQuery( -// command: string, -// context?: string, -// stringify?: boolean, -// ): Promise { -// await this.waitForConnection(); - -// if (!this.connection) { -// return "timeout"; -// } -// const wrapper = queryWrapper(); -// this.connection.k( -// wrapper, -// context ?? ".", -// command, -// !!stringify, -// (err: Error, res: QueryResult) => { -// if (err) { -// this.isError = true; -// this.result = handleQueryResults( -// err.toString(), -// QueryResultType.Error, -// ); -// } -// if (res) { -// this.handleQueryResult(res); -// } -// }, -// ); - -// const result = await this.waitForResult(); - -// if (ext.resultsViewProvider.isVisible() && stringify) { -// if (this.isError) { -// this.isError = false; -// return result; -// } -// return convertStringToArray(result); -// } - -// return result; -// } - -// private async waitForConnection(): Promise { -// let retryCount = 0; -// while (this.connection === undefined) { -// if (retryCount > ext.maxRetryCount) { -// throw new Error("timeout"); -// } -// await delay(500); -// retryCount++; -// } -// } - -// private handleQueryResult = (res: QueryResult): void => { -// if (res.errored) { -// this.isError = true; -// this.result = handleQueryResults( -// res.error + (res.backtrace ? "\n" + res.backtrace : ""), -// QueryResultType.Error, -// ); -// } else { -// this.result = res.result; -// } -// }; - -// private async waitForResult(): Promise { -// while (this.result === undefined || this.result === null) { -// await delay(500); -// } -// const result = this.result; -// this.result = undefined; -// return result; -// } - -// public async executeQueryRaw(command: string): Promise { -// let result; -// let retryCount = 0; -// let error; -// while (this.connection === undefined) { -// if (retryCount > ext.maxRetryCount) { -// return "timeout"; -// } -// await delay(500); -// retryCount++; -// } -// this.connection.k(command, (err: Error, res: string) => { -// if (err) { -// error = err; -// result = ""; -// return; -// } -// result = res; -// }); - -// while (result === undefined || result === null) { -// await delay(500); -// } - -// if (error) { -// throw error; -// } - -// return result; -// } - -// public connect(callback: nodeq.AsyncValueCallback): void { -// nodeq.connect(this.options, (err, conn) => { -// if (err || !conn) { -// commands.executeCommand("setContext", "kdb.connected", false); -// ext.connectionNode = undefined; -// ext.serverProvider.reload(); - -// window.showErrorMessage( -// `Connection to server ${this.options.host}:${this.options.port} failed! Details: ${err?.message}`, -// ); -// ext.outputChannel.appendLine( -// `Connection to server ${this.options.host}:${this.options.port} failed! Details: ${err?.message}`, -// ); -// return; -// } - -// conn.addListener("close", () => { -// ext.outputChannel.appendLine( -// `Connection stopped from ${this.options.host}:${this.options.port}`, -// ); -// this.connected = false; -// }); - -// if (this.connection && this.connected) { -// this.connection.close(() => { -// this.onConnect(err, conn, callback); -// }); -// } else { -// this.onConnect(err, conn, callback); -// } -// }); -// } - -// public update(): void { -// this.updateGlobal(); -// this.updateReservedKeywords(); -// } - -// private updateGlobal() { -// const globalQuery = -// '{[q] t:system"T";tm:@[{$[x>0;[system"T ",string x;1b];0b]};0;{0b}];r:$[tm;@[0;(q;::);{[tm; t; msgs] if[tm;system"T ",string t];\'msgs}[tm;t]];@[q;::;{\'x}]];if[tm;system"T ",string t];r}{do[1000;2+2];{@[{.z.ide.ns.r1:x;:.z.ide.ns.r1};x;{r:y;:r}[;x]]}({:x!{![sv[`;] each x cross `Tables`Functions`Variables; system each "afv" cross enlist[" "] cross enlist string x]} each x} [{raze x,.z.s\'[{x where{@[{1#get x};x;`]~1#.q}\'[x]}` sv\'x,\'key x]}`]),(enlist `.z)!flip (`.z.Tables`.z.Functions`.z.Variables)!(enlist 0#`;enlist `ac`bm`exit`pc`pd`pg`ph`pi`pm`po`pp`ps`pw`vs`ts`s`wc`wo`ws;enlist `a`b`e`f`h`i`k`K`l`o`q`u`w`W`x`X`n`N`p`P`z`Z`t`T`d`D`c`zd)}'; -// this.connection?.k(globalQuery, (err, result) => { -// if (err) { -// window.showErrorMessage( -// `Failed to retrieve kdb+ global variables: '${err.message}`, -// ); -// return; -// } - -// this.updateGlobals(result); -// }); -// } - -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// private updateGlobals(result: any): void { -// const globals = result; -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// const entries: [string, any][] = Object.entries(globals); - -// ext.functions.length = 0; -// ext.tables.length = 0; -// ext.variables.length = 0; - -// entries.forEach(([key, value]) => { -// key = key === "null" ? "." : key + "."; - -// const f = value[key + "Functions"]; -// const t = value[key + "Tables"]; -// let v = value[key + "Variables"]; - -// key = key === "." || key === ".q." ? "" : key; - -// if (f instanceof Array) { -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// f.forEach((obj: any) => ext.functions.push(`${key}${obj}`)); -// } - -// if (t instanceof Array) { -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// t.forEach((obj: any) => ext.tables.push(`${key}${obj}`)); -// } - -// if (v instanceof Array) { -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// v = v.filter((x: any) => !t.includes(x)); -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// v.forEach((obj: any) => ext.variables.push(`${key}${obj}`)); -// } -// }); -// } - -// private updateReservedKeywords() { -// const reservedQuery = ".Q.res"; -// this.connection?.k(reservedQuery, (err, result) => { -// if (err) { -// window.showErrorMessage( -// `Failed to retrieve kdb+ reserved keywords: '${err.message}`, -// ); -// return; -// } - -// ext.keywords = result; -// }); -// } - -// private onConnect( -// err: Error | undefined, -// conn: nodeq.Connection, -// callback: nodeq.AsyncValueCallback, -// ): void { -// this.connected = true; -// this.connection = conn; - -// this.updateGlobal(); -// this.updateReservedKeywords(); - -// callback(err, this); -// } -// } diff --git a/src/services/dataSourceTreeProvider.ts b/src/services/dataSourceTreeProvider.ts index 66b65bee..0b4dd896 100644 --- a/src/services/dataSourceTreeProvider.ts +++ b/src/services/dataSourceTreeProvider.ts @@ -32,6 +32,7 @@ import { createKdbDataSourcesFolder, } from "../utils/dataSource"; +// TODO: DEPRECATED THIS DS PROVIDER WILL BE REMOVED IN VERSION 1.6.0 export class KdbDataSourceProvider implements TreeDataProvider { private _onDidChangeTreeData: EventEmitter< KdbDataSourceTreeItem | undefined | void diff --git a/src/utils/dataSource.ts b/src/utils/dataSource.ts index 2665d175..ea20ea34 100644 --- a/src/utils/dataSource.ts +++ b/src/utils/dataSource.ts @@ -17,7 +17,7 @@ import { ext } from "../extensionVariables"; import { DataSourceFiles } from "../models/dataSource"; import { DataSourcesPanel } from "../panels/datasource"; import { InsightsConnection } from "../classes/insightsConnection"; -import { Uri, workspace, window } from "vscode"; +import { workspace, window } from "vscode"; import { Telemetry } from "./telemetryClient"; export function createKdbDataSourcesFolder(): string {